Project

General

Profile

6709-20230106.patch

Dănuț Filimon, 01/06/2023 02:48 AM

Download (18.7 KB)

View differences:

new/rules/annotations/index_selection.rules 2023-01-05 08:39:54 +0000
114 114
**                           Fixed conversion of sorting by extent fields with non-constant index.
115 115
** 042 ECF 20200906          New ORM implementation.
116 116
** 043 IAS 20210209          Do not use word index field for sorting
117
** 044 DDF 20230105          Use hint to set related_buffer annotation to true if
118
**                           in a FIND.
117 119
*/
118 120
-->
119 121

  
......
187 189
   <worker class="com.goldencode.p2j.schema.SchemaWorker"            namespace="schema" />
188 190
   <worker class="com.goldencode.p2j.uast.ProgressPatternWorker"     namespace="prog" />
189 191
   <worker class="com.goldencode.p2j.convert.IndexSelectionWorker"   namespace="isw" />
192
   <worker class="com.goldencode.p2j.uast.UastHintsWorker"           namespace="uhw" />
190 193
   
191 194
   <!-- variables -->
192 195
   <variable name="record"             type="com.goldencode.ast.Aast" />
......
225 228
   <variable name="tableCount"         type="java.lang.Integer" />
226 229
   <variable name="countingTables"     type="java.lang.Boolean" />
227 230
   <variable name="functypes"          type="java.util.ArrayList" />
231
   <variable name="inFind"             type="java.lang.Boolean" />
232
   <variable name="enableFindFieldRef" type="java.lang.Boolean" />
228 233
   
229 234
   <!-- function libraries -->
230 235
   <include name="common-progress" />
......
350 355
      <rule>functypes.add(prog.func_raw)</rule>
351 356
      <rule>functypes.add(prog.func_memptr)</rule>
352 357
      <rule>functypes.add(prog.func_poly)</rule>
358
      
359
      <rule>inFind = false</rule>
353 360
   </init-rules>
354 361
   
355 362
   <walk-rules>
356 363
   
364
      <!-- if the type is Find and hint is provided -->
365
      <rule>type == prog.KW_FIND
366
         <action>enableFindFieldRef = uhw.getUastBoolean("enable_find_field_reference")</action>
367
         <rule>enableFindFieldRef != null
368
            <action>inFind = enableFindFieldRef</action>
369
         </rule>
370
      </rule>
371
   
357 372
      <!-- query-level initialization -->
358 373
      <rule>
359 374
         (type == prog.open_query or
......
549 564
                  <!-- in a multi-table query, remember that this field
550 565
                       is a reference back to a different but previous
551 566
                       buffer in the same query -->
552
                  <rule on="false">queryBufferOrder.contains(getNoteLong("refid"))
567
                  <rule on="false">queryBufferOrder.contains(getNoteLong("refid")) or inFind
553 568
                     <action>putNote("related_buffer", true)</action>
554 569
                     <action on="false">putNote("related_buffer", false)</action>
555 570
                  </rule>
......
611 626
                     <!-- in a multi-table query, remember that this field
612 627
                          is a reference back to a different but previous
613 628
                          buffer in the same query -->
614
                     <rule>queryBufferOrder.contains(getNoteLong("refid"))
629
                     <rule>queryBufferOrder.contains(getNoteLong("refid")) or inFind
615 630
                        <action>putNote("related_buffer", true)</action>
616 631
                        <action on="false">putNote("related_buffer", false)</action>
617 632
                     </rule>
......
1015 1030
         <action>extentSortFields.clear()</action>
1016 1031
      </rule>
1017 1032
      
1033
      <!-- reset flag -->
1034
      <rule>inFind and type == prog.KW_FIND
1035
         <action>inFind = false</action>
1036
      </rule>
1037
      
1018 1038
   </ascent-rules>
1019 1039
   
1020 1040
   <post-rules>
new/rules/annotations/nested_find.rules 2023-01-05 08:40:17 +0000
13 13
**                           that reference the same buffer. The purpose is to
14 14
**                           create a report where nested finds are classified
15 15
**                           using the NEXT/PREV/LAST/FIRST/WHERE keywords.
16
** 002 DDF 20230105          Changed the annotation value stored to the tree id.
16 17
*/
17 18
 -->
18 19

  
......
78 79
   <variable name="inWhere"          type="java.lang.Boolean" />
79 80
   <variable name="bufferName"       type="java.lang.String" />
80 81
   <variable name="annotationValue"  type="java.lang.String" />
81
   <variable name="annotationObject" type="java.lang.Object" />
82
   <variable name="annotationObject" type="com.goldencode.ast.Aast" />
82 83

  
83 84
   <init-rules>
84 85
      <rule>scopedDict = create("com.goldencode.p2j.util.ScopedSymbolDictionary")</rule>
......
97 98
         <action>recordAst = this.getChildAt(0)</action>
98 99
         <rule>recordAst != null
99 100
            <action>annotationValue = #(java.lang.String) recordAst.getAnnotation("bufname")</action>
100
            <action>annotationObject = recordAst.getAnnotation("bufname")</action>
101
            <action>scopedDict.addSymbol(false, annotationValue, annotationObject)</action>
101
            <action>scopedDict.addSymbol(false, annotationValue, this.parent)</action>
102 102
         </rule>
103 103
      </rule>
104 104
      
......
117 117
           previously -->
118 118
      <rule>inWhere and scopedDict.size() > 0 and evalLib("fields")
119 119
         <action>bufferName = #(java.lang.String) this.getAnnotation("bufname")</action>
120
         <rule>scopedDict.lookupSymbol(bufferName) != null
121
            <action>putReferenceNote(currentFindAst.getId(), "nested_find", true)</action>
120
         <action>annotationObject = #(com.goldencode.ast.Aast) scopedDict.lookupSymbol(bufferName)</action>
121
         <rule>annotationObject != null
122
            <action>putReferenceNote(currentFindAst.getId(), "nested_find", annotationObject.getId())</action>
122 123
         </rule>
123 124
      </rule>
124 125
   </walk-rules>
new/rules/convert/expressions.rules 2023-01-05 08:40:40 +0000
232 232
**                           initialized at the method's execution, and not at the caller's arguments.
233 233
**                           (backed out CA/20210428).
234 234
**     GES 20210722          Exclude Java method calls from built-in OO 4GL processing.
235
**     DDF 20230105          Include hint value if exists when the casting to P2JQuery.Parameter is inserted.
235 236
*/
236 237
-->
237 238

  
......
1306 1307
               <rule>
1307 1308
                  getNoteBoolean("deferred") and
1308 1309
                  !(isNote("delegated_eval") and getNoteBoolean("delegated_eval"))
1309
                  <action>lastid = createJavaAst(java.cast, "P2JQuery.Parameter", lastid)</action>
1310
                  <action>lastid = createJavaAst(java.lambda, "", lastid)</action>
1311
                  <action>createJavaAst(java.lparens, "", lastid)</action>
1310
                  <!-- use hint if provided -->
1311
                  <rule>(uhw.getUastBoolean("enable_find_field_reference") != null) and
1312
                        uhw.getUastBoolean("enable_find_field_reference")         
1313
                     <action on="false">lastid = createJavaAst(java.cast, "P2JQuery.Parameter", lastid)</action>
1314
                     <action on="false">lastid = createJavaAst(java.lambda, "", lastid)</action>
1315
                     <action on="false">createJavaAst(java.lparens, "", lastid)</action>
1316
                  </rule>
1312 1317
               </rule>
1313 1318
               
1314 1319
               <!-- dynamic where subscripts in query substitutions need to
new/src/com/goldencode/p2j/jmx/FwdJMX.java 2023-01-05 08:41:30 +0000
22 22
**                    OrmDataSetParam, OrmDynamicDataSetParam).
23 23
**                  - OpenClient parameter processing (AppserverAddTableMetaData, ApperverGetJavaParameter, 
24 24
**                    AppserverGetOutputParameter).
25
**     DDF 20230105 Added a counter for nested find queries (refs: #6709).
25 26
*/ 
26 27

  
27 28
/*
......
524 525
      /** Outgoing network traffic */
525 526
      NetworkWrites,
526 527
      /** Widget attributes flush count */
527
      WidgetAttrFlushes;
528
      WidgetAttrFlushes,
529
      /** Counter for nested find queries */
530
      NestedFindQueries;
528 531
      
529 532
      /** Counter instance */
530 533
      private final SimpleLongCounter counter = new SimpleLongCounter();
new/src/com/goldencode/p2j/persist/BufferManager.java 2023-01-05 08:41:51 +0000
466 466
**                           block scope.
467 467
**     CA  20221010          Performance improvements - avoid the ProcedureData lookup, by keeping a parallel 
468 468
**                           stack of this data for THIS-PROCEDURE.  Refs #6826
469
**     DDF 20230105          Added functionality for tracking nested find at runtime. A flag from directory.xml
470
**                           is stored and used to enable runtime tracking. (refs: #6709)
469 471
*/
470 472

  
471 473
/*
......
530 532
import java.util.logging.*;
531 533

  
532 534
import com.goldencode.cache.*;
535
import com.goldencode.p2j.cfg.Configuration;
533 536
import com.goldencode.p2j.convert.*;
537
import com.goldencode.p2j.directory.DirectoryService;
534 538
import com.goldencode.p2j.oo.lang.*;
535 539
import com.goldencode.p2j.persist.dirty.*;
536 540
import com.goldencode.p2j.persist.id.*;
......
698 702

  
699 703
   /** Track the external scopes pushed on {@link BufferManager}. */
700 704
   private final Stack<Boolean> externalScope = new Stack<>();
705
   
706
   /** Maps a RecordBuffer and the related P2JQuery from a forEach block */
707
   private Map<RecordBuffer, P2JQuery> forEachMap = new ConcurrentHashMap<>();
708
   
709
   /** Configuration value from {@code directory.xml} that enables nested find tracking */
710
   public static final boolean ENABLE_NESTED_FIND_TRACKING;
711
   
712
   static
713
   {
714
      boolean enableNestedFindTracking = false;
715
      
716
      if (Configuration.isRuntimeConfig())
717
      {
718
         DirectoryService ds = DirectoryService.getInstance();
719
         if (!ds.bind())
720
         {
721
            throw new RuntimeException("Directory bind failed");
722
         }
723
         
724
         try
725
         {
726
            String path = "persistence/enable-nested-find-tracking";
727
            enableNestedFindTracking = Utils.getDirectoryNodeBoolean(ds, path, false, false);
728
         }
729
         finally
730
         {
731
            ds.unbind();
732
         }
733
      }
734
      
735
      ENABLE_NESTED_FIND_TRACKING = enableNestedFindTracking;
736
   }
701 737

  
702 738
   /**
703 739
    * Constructor; instances of this class are context-local and must be accessed using the static
......
2728 2764
   }
2729 2765
   
2730 2766
   /**
2767
    * Add an element to the forEachMap.
2768
    * If the key already exists, the value is overridden.
2769
    * 
2770
    * @param   rb
2771
    *          RecordBuffer of a P2JQuery from a forEach block
2772
    * @param   q
2773
    *          P2JQuery that is component of a forEach block
2774
    */
2775
   public static void addForEachMap(RecordBuffer rb, P2JQuery q)
2776
   {
2777
      BufferManager bm = context.get();
2778
      bm.forEachMap.put(rb, q);
2779
   }
2780
   
2781
   /**
2782
    * Remove an element from the forEachMap.
2783
    * 
2784
    * @param   rb
2785
    *          RecordBuffer of a P2JQuery from a forEach block.
2786
    */
2787
   public static void removeForEachMap(RecordBuffer rb)
2788
   {
2789
      BufferManager bm = context.get();
2790
      bm.forEachMap.remove(rb);
2791
   }
2792
   
2793
   /**
2794
    * Lookup the given key in the forEachMap.
2795
    * 
2796
    * @param   rb
2797
    *          RecordBuffer that is looked up.
2798
    *          
2799
    * @return  true/false
2800
    */
2801
   public static boolean lookupForEachValue(RecordBuffer rb) 
2802
   {
2803
      BufferManager bm = context.get();
2804
      return bm.forEachMap.containsKey(rb);
2805
   }
2806
   
2807
   /**
2731 2808
    * Container for batch assign mode information.
2732 2809
    */
2733 2810
   private static class BatchModeData
new/src/com/goldencode/p2j/persist/FindQuery.java 2023-01-05 08:41:59 +0000
63 63
** 024 ECF 20210806          Corrected CAN-FIND return value in event of fatal error. Fixed nested query
64 64
**                           error detection/reporting.
65 65
**     ECF 20210911          Javadoc fix.
66
**     DDF 20230105          Added method for checking if FindQuery is nested in a FOR EACH. Tracking is
67
**                           done at runtime only if it's enabled through BufferManager.ENABLE_NESTED_FIND_TRACKING
68
**                           value.
66 69
*/
67 70

  
68 71
/*
......
121 124
package com.goldencode.p2j.persist;
122 125

  
123 126
import java.util.function.*;
127

  
128
import com.goldencode.p2j.jmx.*;
124 129
import com.goldencode.p2j.persist.lock.*;
125 130
import com.goldencode.p2j.util.*;
126 131

  
......
161 166
   /** Flag indicating whether buffer is updated by query */
162 167
   private boolean readOnly = false;
163 168
   
169
   /** Counter for measuring nested find initializations */
170
   private static final SimpleCounter NestedFindCounter = SimpleCounter.getInstance(
171
            FwdJMX.Counter.NestedFindQueries
172
   ); 
173
   
164 174
   /**
165 175
    * Basic constructor which defaults record lock type to
166 176
    * <code>LockType.SHARE</code>.
......
415 425
      super();
416 426
      super.initialize(dmo, where, whereExpr, sort, null, inverse, args, lockType);
417 427
      
428
      if (BufferManager.ENABLE_NESTED_FIND_TRACKING)
429
      {
430
         System.out.println("Current FINDQuery nested status: " + Boolean.toString(isNested()));
431
      }
432
      
418 433
      // if the NO-ERROR clause is specified, then a QOEE must not be thrown
419 434
      setLenientOffEnd(getBuffer().txHelper.errHlp.isSilent());
420 435
      setErrorIfNull(true);
......
888 903
      
889 904
      return true;
890 905
   }
906
   
907
   /**
908
    * Check if query is nested in a FOR EACH.
909
    * 
910
    * @return  true if it's nested, false if not
911
    */
912
   private boolean isNested()
913
   {
914
      if (hasWhereExpression())
915
      {
916
         return false;
917
      }
918
      
919
      Object[] values = getArgs();
920
      
921
      if (values == null)
922
      {
923
         return false;
924
      }
925
      
926
      for (Object val : values)
927
      {
928
         if (!(val instanceof FieldReference))
929
         {
930
            continue;
931
         }
932
         
933
         final FieldReference ref = (FieldReference) val;
934
         RecordBuffer valueRecord = ref.getParentBuffer();
935
         if (valueRecord == null)
936
         {
937
            continue;
938
         }
939
         
940
         if (BufferManager.lookupForEachValue(valueRecord))
941
         {
942
            NestedFindCounter.update(1L);
943
            return true;
944
         }
945
      }
946
      return false;
947
   }
891 948
}
new/src/com/goldencode/p2j/util/BlockManager.java 2023-01-05 08:42:11 +0000
227 227
**     TJD 20220504          Java 11 compatibility minor changes
228 228
**     CA  20221123          If an 'object' instance is assigned in the FINALLY block and also referenced by 
229 229
**                           the RETURN statement, then do not remove it from 'pendingAssign'.
230
**     DDF 20230105          Saved the offEndQueries for nested find tracking. offEndQueries are cleared after the
231
**                           forEach block is finished, while tracking requires the components to be available
232
**                           in the body block.
230 233
*/
231 234

  
232 235
/*
......
293 296
import com.goldencode.p2j.directory.*;
294 297
import com.goldencode.p2j.main.*;
295 298
import com.goldencode.p2j.oo.lang.*;
299
import com.goldencode.p2j.persist.*;
296 300
import com.goldencode.p2j.security.ContextLocal;
297
import com.goldencode.p2j.persist.QueryOffEndException;
298
import com.goldencode.p2j.persist.QueryOffEndListener;
299 301

  
300 302
// the following are dependencies on the UI package which we would prefer to
301 303
// eliminate if the services can be cleanly abstracted without making the
......
10500 10502
      
10501 10503
      wa.tm.pushScope(label, ttype, props, false, false, true, true, btype, block);
10502 10504
      
10505
      Set<P2JQuery> forEachQueries = null;
10503 10506
      try
10504 10507
      {
10505 10508
         try
......
10514 10517
         }
10515 10518
         finally
10516 10519
         {
10520
            if (BufferManager.ENABLE_NESTED_FIND_TRACKING)
10521
            {
10522
               forEachQueries = wa.tm.getOffEndQueries();
10523
               for (P2JQuery query : forEachQueries)
10524
               {
10525
                  if (query.getRecordBuffers() == null)
10526
                  {
10527
                     continue;
10528
                  }
10529
                  
10530
                  for (RecordBuffer rb : query.getRecordBuffers())
10531
                  {
10532
                     BufferManager.addForEachMap(rb, query);
10533
                  }
10534
               }
10535
            }
10517 10536
            // after block initialization is finished, the off end listeners
10518 10537
            // for all the buffers in the collected queries are saved
10519 10538
            wa.tm.stopOffEndRegistration();
......
10661 10680
      
10662 10681
      finally
10663 10682
      {
10683
         if (forEachQueries != null)
10684
         {
10685
            for (P2JQuery query : forEachQueries)
10686
            {
10687
               if (query.getRecordBuffers() == null)
10688
               {
10689
                  continue;
10690
               }
10691
               
10692
               for (RecordBuffer rb : query.getRecordBuffers())
10693
               {
10694
                  BufferManager.removeForEachMap(rb);
10695
               }
10696
            }
10697
         }
10664 10698
         wa.tm.popScope();
10665 10699
      }
10666 10700
   }
new/src/com/goldencode/p2j/util/TransactionManager.java 2023-01-05 08:42:30 +0000
511 511
**                           a set instead of a list, as their order is not important.  Refs #6824
512 512
**     CA  20221010          Performance improvements - avoid the ProcedureData lookup, by keeping a parallel 
513 513
**                           stack of this data for THIS-PROCEDURE.  Refs #6826
514
**     DDF 20230105          Added functionality to retrieve offEndQuery value.
514 515
*/
515 516

  
516 517
/*
......
7712 7713
   }
7713 7714
   
7714 7715
   /**
7716
    * Get the offEndQueries using the context local work area.
7717
    * 
7718
    * @param   wa
7719
    *          Context local work area.
7720
    *       
7721
    * @return  offEndQueries of the context local work area.
7722
    */
7723
   public static Set<P2JQuery> getOffEndQueries(WorkArea wa)
7724
   {
7725
      return wa.offEndQueries;
7726
   }
7727
   
7728
   /**
7715 7729
    * Helper to expose transaction state in a way that avoids context local lookups.
7716 7730
    */
7717 7731
   public static class TransactionHelper
......
10185 10199
         copy.addAll(wa.blocks);
10186 10200
         return copy;
10187 10201
      }
10202

  
10203
      /**
10204
       * Get the offEndQueries using the context local work area.
10205
       * 
10206
       * @return  offEndQueries of the context local work area.
10207
       */
10208
      public Set<P2JQuery> getOffEndQueries()
10209
      {
10210
         return TransactionManager.getOffEndQueries(wa);
10211
      }
10188 10212
   }
10189 10213
   
10190 10214
   /**