Project

General

Profile

6695-2.patch

Radu Apetrii, 11/09/2022 12:42 PM

Download (33.3 KB)

View differences:

new/src/com/goldencode/p2j/persist/AdaptiveQuery.java 2022-11-09 10:12:47 +0000
335 335
**                           the scopeable is 'active' (i.e. unnamed streams or accumulators are used).  This
336 336
**                           allows a lazy registration of scopeables, to avoid the unnecessary overhead of
337 337
**                           processing all the scopeables for each and every block.
338
**     RAA 20221010          Added method isAutoFetch() for when lazy fetching is intended.
339
**     RAA 20221027          Added a 'get' method with a LazyFetching parameter for when lazy fetching
340
**                           is intended.
338 341
*/
339 342

  
340 343
/*
......
3276 3279
   protected void fetch(boolean available, LockType lockType, boolean errorIfNull)
3277 3280
   throws MissingRecordException
3278 3281
   {
3282
      if (available && getResults().isAutoFetch())
3283
      {
3284
         return;
3285
      }
3286

  
3279 3287
      super.fetch(available, lockType, errorIfNull);
3280 3288
      
3281 3289
      if (!isScrolling() && !foundFirst && available && offEnd == OffEnd.NONE)
......
3790 3798
      }
3791 3799
      
3792 3800
      /**
3801
       * Is the result delegate responsible for fetching? This is usually true when using
3802
       * query delegates which handle the fetching process already.
3803
       * 
3804
       * @return   {@code true} for complex results which also do the fetching
3805
       * 
3806
       */
3807
      @Override
3808
      public boolean isAutoFetch()
3809
      {
3810
         return true;
3811
      }
3812
      
3813
      /**
3793 3814
       * Get the array of objects at the current result row.
3794 3815
       *
3795 3816
       * @return  Object array or <code>null</code>.
3796 3817
       */
3797 3818
      public Object[] get()
3798 3819
      {
3799
         int len = buffers.length;
3800
         Object[] row = new Object[len];
3801
         for (int i = 0; i < len; i++)
3820
         return get(null);
3821
      }
3822
      
3823
      /**
3824
       * Get the array of objects at the current result row if lazy fetching allows it.
3825
       *
3826
       * @param   fetching
3827
       *          The instance responsible with lazy fetching.
3828
       * @return  Object array or <code>null</code>.
3829
       */
3830
      public Object[] get(LazyFetching fetching)
3831
      {
3832
         // if lazy fetching is not intended at all or
3833
         // if lazy fetching is intended and getting the full record is OK
3834
         if (fetching == null || fetching.isFullRecordOk())
3802 3835
         {
3803
            row[i] = get(i);
3836
            int len = buffers.length;
3837
            Object[] row = new Object[len];
3838
            for (int i = 0; i < len; i++)
3839
            {
3840
               row[i] = get(i);
3841
            }
3842
            
3843
            return row;
3804 3844
         }
3805 3845
         
3806
         return row;
3846
         throw new IllegalStateException("Lazy Fetching is used, but the record is already hydrated");
3807 3847
      }
3808 3848
      
3809 3849
      /**
new/src/com/goldencode/p2j/persist/PreselectQuery.java 2022-11-09 10:17:54 +0000
585 585
**     OM  20220530          Fixed flush of nursery (only the affected index).
586 586
**     OM  20220701          Flatten calls to initialize().
587 587
**     CA  20221006          Added JMX instrumentation for query assemble. Refs #6814
588
**     RAA 20221010          Added class PreselectLazyFetching which enables the possibility of lazy fetching
589
**                           for Preselect queries on temporary no-undo tables.
588 590
**     CA  20221013          In 'repositionByID', if the row number is after the last row in the ResultSet,
589 591
**                           assume an error (query off-end) and do not try to fetch the record.
590 592
*/
......
762 764
   /** Has query been registered for resource cleanup? */
763 765
   private boolean regCleaner = false;
764 766
   
767
   /** Instance of lazy fetching. */
768
   private LazyFetching fetching = new PreselectLazyFetching();
769
   
765 770
   /** Cleaner executed when this query's block is exit. */
766 771
   private final Finalizable cleaner = new Finalizable()
767 772
   {
......
5669 5674
         }
5670 5675
         else
5671 5676
         {
5672
            Object[] data = available ? results.get() : null;
5673
            coreFetch(data, lockType, errorIfNull, false);
5677
            if (!results.isAutoFetch())
5678
            {
5679
               Object[] data = available ? results.get(fetching) : null;
5680
               coreFetch(data, lockType, errorIfNull, false);
5681
            }   
5674 5682
            
5675 5683
            if (available)
5676 5684
            {
......
5732 5740
   {
5733 5741
      int recFetched = 0;
5734 5742
      Iterator<QueryComponent> iter = components();
5743
      
5735 5744
      for (int i = 0; iter.hasNext(); i++)
5736 5745
      {
5737 5746
         QueryComponent comp = iter.next();
5738 5747
         RecordBuffer buffer = comp.getBuffer();
5748

  
5749
         if (data != null && data[i] == null)
5750
         {
5751
            recFetched++;
5752
            continue;
5753
         }
5754
         
5739 5755
         boolean dirtyCopy = false;
5740 5756
         Record dmo = null;
5741 5757
         LockType lt = lockType;
......
6669 6685
      @Override
6670 6686
      public Object[] get()
6671 6687
      {
6672
         return (cursor == 0) ? new Object[] { templateRowid } : null; 
6688
         return get(null);
6689
      }
6690
      
6691
      /**
6692
       * Get the array of objects at the current result row if lazy fetching allows it.
6693
       *
6694
       * @param   fetching
6695
       *          The instance responsible with lazy fetching.
6696
       * @return  Object array or {@code null}.
6697
       */
6698
      @Override
6699
      public Object[] get(LazyFetching fetching)
6700
      {
6701
         if (cursor != 0)
6702
            return null;
6703
         
6704
         // if lazy fetching is not intended at all or
6705
         // if lazy fetching is intended and getting the full record is OK
6706
         if (fetching == null || fetching.isFullRecordOk())
6707
         {
6708
            return new Object[] { templateRowid };
6709
         }
6710
         
6711
         throw new IllegalStateException("Lazy Fetching is used, but the record is already hydrated");
6673 6712
      }
6674 6713
      
6675 6714
      /**
......
6791 6830
         // else cursor is -1 (before), 0 (on single record), 1 (after)
6792 6831
      }
6793 6832
   }
6833
   
6834
   /**
6835
    * Class that implements the concept of {@link LazyFetching} for {@link PreselectQuery}.
6836
    * It provides a quick response as to whether a {@link Record} should be lazy fetched or not.
6837
    */
6838
   class PreselectLazyFetching
6839
   implements LazyFetching
6840
   {
6841

  
6842
      /**
6843
       * Method to check if a {@link Record} should be fully/partially fetched or not.
6844
       * Fully fetched means that a {@code Record} should be retrieved from the database,
6845
       * partially fetched means that a {@code Record} should be retrieved from the cache.
6846
       * This method does not make the difference between fully and partially fetching. It only matters if
6847
       * the lazy fetching layer is being bypassed or not (what happens after that is not its job).
6848
       * 
6849
       * This implementation is specific to this class because we compare the primary key of the existing
6850
       * record with the one that is about to be put in the {@link RecordBuffer}.
6851
       * For other types of Queries different implementations could be required.
6852
       * 
6853
       * @param   comp
6854
       *          The number of the {@link QueryComponent} for which we check it's {@link RecordBuffer}.
6855
       * @param   id
6856
       *          The id of the {@code Record} that is about to be put in the {@code RecordBuffer}.
6857
       * @return  {@code true} if a {@code Record} should be fully/partially fetched 
6858
       *          (does not matter which one), {@code false} otherwise.
6859
       */
6860
      @Override
6861
      public boolean shouldFetch(int comp, Long id)
6862
      {
6863
         QueryComponent component = components.get(comp);
6864
         return component.checkFetching(id);
6865
      }
6866

  
6867
      /**
6868
       * Setter for the {@code oldId}, which is responsible with knowing the id of the
6869
       * last {@code Record} that was inside the {@link RecordBuffer}.
6870
       * 
6871
       * @param   comp
6872
       *          The number of the {@link QueryComponent} for which we check it's {@code RecordBuffer}.
6873
       * @param   id
6874
       *          The id of the old {@code Record}.
6875
       */
6876
      @Override
6877
      public void setOldId(int comp, Long id)
6878
      {
6879
         components.get(comp).setOldId(id);
6880
      }
6881

  
6882
      /**
6883
       * Method for checking if it is OK to retrieve the full record. Most of the times, the implementation
6884
       * of this method will return {@code true}. Only in very few cases, the retrieval of the full record
6885
       * will not benefit the cause.
6886
       * 
6887
       * @return  {@code true} if we are fine with working with the full record, {@code false} otherwise.  
6888
       */
6889
      @Override
6890
      public boolean isFullRecordOk()
6891
      {
6892
         return true;
6893
      }
6894
      
6895
   }
6794 6896
}
6795 6897

  
new/src/com/goldencode/p2j/persist/PresortCompoundQuery.java 2022-11-09 10:12:47 +0000
30 30
** 012 OM  20180620          Added support for dynamically configured sort criteria.
31 31
** 013 ECF 20181106          Added runtime support for {FIRST|LAST}-OF methods.
32 32
** 014 ECF 20200906          New ORM implementation.
33
** 015 RAA 20221027          Added a 'get' method with a LazyFetching parameter for when lazy fetching
34
**                           is intended.
33 35
*/
34 36

  
35 37
/*
......
90 92
import java.io.*;
91 93
import java.util.*;
92 94
import com.goldencode.p2j.persist.lock.*;
95
import com.goldencode.p2j.persist.orm.*;
93 96
import com.goldencode.p2j.util.*;
94 97

  
95 98
/**
......
651 654
       */
652 655
      public Object[] get()
653 656
      {
654
         return row;
657
         return get(null);
658
      }
659
      
660
      /**
661
       * Get the array of objects at the current result row if lazy fetching allows it.
662
       *
663
       * @param   fetching
664
       *          The instance responsible with lazy fetching.
665
       * @return  Object array or <code>null</code>.
666
       */
667
      public Object[] get(LazyFetching fetching)
668
      {
669
         // if lazy fetching is not intended at all or
670
         // if lazy fetching is intended and getting the full record is OK
671
         if (fetching == null || fetching.isFullRecordOk())
672
         {
673
            return row;
674
         }
675
         
676
         throw new IllegalStateException("Lazy Fetching is used, but the record is already hydrated");   
655 677
      }
656 678
      
657 679
      /**
new/src/com/goldencode/p2j/persist/Presorter.java 2022-11-09 10:12:47 +0000
34 34
** 016 ECF 20190427          Fixed results caching.
35 35
** 017 ECF 20200906          New ORM implementation.
36 36
** 018 CA  20210923          Fixed SortedResults, when the component retrieves only the DMO id.
37
** 019 RAA 20221027          Added a 'get' method with a LazyFetching parameter for when lazy fetching
38
**                           is intended.
37 39
*/
38 40

  
39 41
/*
......
96 98
import java.util.function.*;
97 99
import com.goldencode.p2j.util.*;
98 100
import com.goldencode.p2j.persist.event.SessionListener;
101
import com.goldencode.p2j.persist.orm.*;
99 102

  
100 103
/**
101 104
 * This helper class performs client-side (i.e., relative to the database
......
934 937
       */
935 938
      public Object[] get()
936 939
      {
940
         return get(null);
941
      }
942
      
943
      /**
944
       * Get the array of objects at the current result row if lazy fetching allows it.
945
       *
946
       * @param   fetching
947
       *          The instance responsible with lazy fetching.
948
       * @return  Object array or <code>null</code>.
949
       */
950
      public Object[] get(LazyFetching fetching)
951
      {
937 952
         if (scrolling)
938 953
         {
939
            return super.get();
954
            return super.get(fetching);
940 955
         }
941 956
         else
942 957
         {
943
            Object[] datum = (Object[]) currentRow;
944
            
945
            return datum;
958
            // if lazy fetching is not intended at all or
959
            // if lazy fetching is intended and getting the full record is OK
960
            if (fetching == null || fetching.isFullRecordOk())
961
            {
962
               Object[] datum = (Object[]) currentRow;
963
               return datum;
964
            }
965

  
966
            throw new IllegalStateException("Record is not hydrated and should be, in order to be used");
946 967
         }
947 968
      }
948 969
      
new/src/com/goldencode/p2j/persist/ProgressiveResults.java 2022-11-09 10:12:47 +0000
138 138
**     EVL 20190822          Adding NPE protection for isResultSetCached.
139 139
** 039 ECF 20200419          Removed Hibernate dependencies.
140 140
** 040 IAS 20220720          Fixed iteration logic (multiple iterations in different directions).
141
** 041 RAA 20221010          Added a 'get' method with a LazyFetching parameter for when lazy fetching
142
**                           is intended.
141 143
*/
142 144

  
143 145
/*
......
199 201
import java.util.*;
200 202
import java.util.logging.*;
201 203
import com.goldencode.p2j.persist.event.*;
204
import com.goldencode.p2j.persist.orm.*;
202 205
import com.goldencode.p2j.util.*;
203 206
import com.goldencode.p2j.util.ErrorManager;
204 207

  
......
459 462
    */
460 463
   public Object[] get()
461 464
   {
465
      return get(null);
466
   }
467
   
468
   /**
469
    * Get the array of objects at the current result row.
470
    *
471
    * @param   fetching
472
    *          The instance responsible with lazy fetching. 
473
    * @return  Object array or <code>null</code>.
474
    */
475
   public Object[] get(LazyFetching fetching)
476
   {
462 477
      if (position < 0)
463 478
      {
464 479
         return null;
465 480
      }
466 481
      
482
      // we can use cache if lazy fetching is not intended at all or
483
      // if lazy fetching is intended and getting the full record is OK
484
      boolean canUseCache = fetching == null || fetching.isFullRecordOk();
485
      
467 486
      // If we have a cache and it contains the requested record, retrieve from the cache.
468
      if (cache != null && position < cache.size())
487
      if (canUseCache && cache != null && position < cache.size())
469 488
      {
470 489
         return cache.get(position);
471 490
      }
......
476 495
         Results results = getResults(bracket);
477 496
         if (results != null)
478 497
         {
479
            return results.get();
498
            return results.get(fetching);
480 499
         }
481 500
      }
482 501
      catch (Exception exc)
new/src/com/goldencode/p2j/persist/QueryComponent.java 2022-11-09 10:12:47 +0000
28 28
** 014 CA  20191009 Added where and sort clause translation in case of bound buffers.
29 29
** 015 ECF 20200906 New ORM implementation.
30 30
** 016 ECF 20210820 Retrofit for query substitution parameter preprocessing fixes.
31
** 017 RAA 20221010 Added the possibility of checking if fetching is necessary for this component.
31 32
*/
32 33

  
33 34
/*
......
164 165
   /** Index information string as it is returned by INDEX-INFORMATION. */
165 166
   private String indexInfo = null;
166 167
   
168
   /** The id of the old Record that was in the buffer. */
169
   private Long oldId = null;
170
   
167 171
   /**
168 172
    * The list of dynamic filters. These are filters added dynamically, at runtime and can also be
169 173
    * removed dynamically.
......
828 832
   }
829 833
   
830 834
   /**
835
    * Method used for checking if fetching is necessary for this component.
836
    * 
837
    * @param   id
838
    *          The id of the {@code Record} that will potentially be fetched.
839
    * @return  true if the buffer needs to fetch this record, or false otherwise.
840
    */
841
   public boolean checkFetching(Long id)
842
   {
843
      Record record = buffer.getCurrentRecord();
844
      if (record == null)
845
      {
846
         return true;
847
      }
848
      
849
      Long bufferId = record.primaryKey();
850
      if (bufferId != null && id.equals(bufferId) && id.equals(oldId))
851
      {
852
         return false;
853
      }
854
     
855
      return true;
856
   }
857
   
858
   /**
859
    * Setter for the old record's id.
860
    * 
861
    * @param   id
862
    *          The id of the record that was just fetched.
863
    */
864
   public void setOldId(Long id)
865
   {
866
      oldId = id;
867
   }
868
   
869
   /**
831 870
    * Set the record buffer for this component's query.
832 871
    * 
833 872
    * @param    buffer
new/src/com/goldencode/p2j/persist/Results.java 2022-11-09 10:12:47 +0000
14 14
** 004 ECF 20190427          Fixed results caching.
15 15
** 005 SVL 20191002          Added addRow.
16 16
** 006 ECF 20200906          New ORM implementation.
17
** 007 RAA 20221010          Added a 'get' method with a LazyFetching parameter for when lazy fetching
18
**                           is intended.
17 19
*/
18 20

  
19 21
/*
......
71 73

  
72 74
package com.goldencode.p2j.persist;
73 75

  
76
import com.goldencode.p2j.persist.orm.*;
77

  
74 78
/**
75 79
 * An abstraction layer between a joinable query implementation and its results.  This interface
76 80
 * defines methods for manipulating a results set using a scrollable cursor paradigm.  Each row
......
122 126
   public boolean isLast();
123 127
   
124 128
   /**
129
    * Is the result delegate responsible for fetching? This is usually true when using
130
    * query delegates which handle the fetching process already.
131
    * 
132
    * @return   {@code true} for complex results which also do the fetching.
133
    * 
134
    */
135
   default public boolean isAutoFetch() 
136
   {
137
      return false;
138
   }
139
   
140
   /**
125 141
    * Get the array of objects at the current result row.
126 142
    *
127 143
    * @return  Object array or {@code null}.
......
129 145
   public Object[] get();
130 146
   
131 147
   /**
148
    * Get the array of objects at the current result row. The default method involves no lazy fetching.
149
    * If lazy fetching is desired, then this method needs to be implemented.
150
    * 
151
    * @param   fetching
152
    *          The instance responsible with lazy fetching.
153
    * @return  Array of {@code Object}s and {@code null}s.
154
    */
155
   default public Object[] get(LazyFetching fetching) 
156
   {
157
      if (fetching != null)
158
      {
159
         throw new IllegalStateException(this.getClass().getName() + 
160
                                         " does not implement get() with onlyDifferences.");
161
      }
162
      return get();
163
   }
164
   
165
   /**
132 166
    * Get the object at the current result row, at the specified column.
133 167
    *
134 168
    * @param   column
......
241 275
   {
242 276
      throw new IllegalStateException("Cannot add a row for this type of results");
243 277
   }
244
}
278
}
new/src/com/goldencode/p2j/persist/ResultsAdapter.java 2022-11-09 10:12:47 +0000
24 24
**                           to true.
25 25
** 007 ECF 20190427          Fixed results caching.
26 26
** 008 ECF 20200906          New ORM implementation.
27
** 009 RAA 20221010          Added a 'get' method with a LazyFetching parameter for when lazy fetching
28
**                           is intended.
27 29
*/
28 30

  
29 31
/*
......
83 85

  
84 86
import java.io.*;
85 87

  
88
import com.goldencode.p2j.persist.orm.*;
89

  
86 90
/**
87 91
 * An implementation of the {@code Results} interface which delegates all work to another {@code
88 92
 * Results} implementation.  A worker can be connected at any time using {@link #setResults}, or
......
203 207
   }
204 208
   
205 209
   /**
210
    * Is the result delegate responsible for fetching? This is usually true when using
211
    * query delegates which handle the fetching process already.
212
    * 
213
    * @return   {@code true} for complex results which also do the fetching.
214
    * 
215
    */
216
   @Override
217
   public boolean isAutoFetch()
218
   {
219
      return results.isAutoFetch();
220
   }
221
   
222
   /**
206 223
    * Get the array of objects at the current result row.
207 224
    *
208 225
    * @return  Object array or {@code null}.
......
211 228
   {
212 229
      return results.get();
213 230
   }
231

  
232
   /**
233
    * Get the array of objects at the current result row if lazy fetching allows it.
234
    * 
235
    * @param   fetching
236
    *          The instance responsible with lazy fetching.
237
    * @return  Object array or {@code null}.
238
    */
239
   public Object[] get(LazyFetching fetching)
240
   {
241
      return results.get(fetching);
242
   }
214 243
   
215 244
   /**
216 245
    * Get the object at the current result row, at the specified column.
......
405 434
         provider.provideNewResults(this);
406 435
      }
407 436
   }
408
}
437
}
new/src/com/goldencode/p2j/persist/ScrollingResults.java 2022-11-09 10:12:47 +0000
20 20
**                           first record (and we are actually on/before the first row). But, in postgresql
21 21
**                           JDBC driver, doing a -1 scroll will position us on the last row (it circles
22 22
**                           back from the last row if the value is negative!).
23
** 009 RAA 20221010          Added a 'get' method with a LazyFetching parameter for when lazy fetching
24
**                           is intended.
23 25
*/
24 26

  
25 27
/*
......
197 199
   }
198 200
   
199 201
   /**
202
    * Get an array of objects or nulls at the current result row if lazy fetching allows it.
203
    * 
204
    * @param   fetching
205
    *          The instance responsible with lazy fetching.  
206
    * @return  Object array or <code>null</code>.
207
    */
208
   public Object[] get(LazyFetching fetching)
209
   {
210
      return results.get(fetching);
211
   }
212
   
213
   /**
200 214
    * Get the object at the current result row, at the specified column.
201 215
    *
202 216
    * @param   column
new/src/com/goldencode/p2j/persist/SimpleResults.java 2022-11-09 10:12:47 +0000
23 23
** 010 ECF 20190427          Fixed results caching.
24 24
** 011 SVL 20191002          Added addRow.
25 25
** 012 ECF 20200906          New ORM implementation.
26
** 013 RAA 20221010          Added a 'get' method with a LazyFetching parameter for when lazy fetching
27
**                           is intended.
26 28
*/
27 29

  
28 30
/*
......
82 84

  
83 85
import java.util.*;
84 86

  
87
import com.goldencode.p2j.persist.orm.*;
88

  
85 89
/**
86 90
 * A simple implementation of {@code Results} which stores row data in a list provided to the
87 91
 * constructor. The row data consists of a list of array objects. Each object in the array is
......
209 213
    */
210 214
   public Object[] get()
211 215
   {
216
      return get(null);
217
   }
218
   
219
   /**
220
    * Get the array of objects at the current result row.
221
    * Because {@code SimpleResults} is meant to provide database results as fast as possible,
222
    * checks for Lazy Fetching are skipped here 
223
    * (which also means that future implementations of Lazy Fetching here will not be considered).
224
    *
225
    * @param   fetching
226
    *          The instance responsible with lazy fetching.
227
    * @return  Object array or {@code null}.
228
    */
229
   public Object[] get(LazyFetching fetching)
230
   {
212 231
      if (position < 0 || position > getNumberOfLoadedRows() - 1)
213 232
      {
214 233
         return null;
215 234
      }
216
      
235

  
217 236
      Object res = rows.get(position);
218 237
      if (res instanceof Object[])
219 238
      {
......
223 242
      {
224 243
          return new Object[] { res };
225 244
      }
226
   }
245
      
246
   } 
227 247
   
228 248
   /**
229 249
    * Get the object at the current result row, at the specified column.
new/src/com/goldencode/p2j/persist/orm/LazyFetching.java 2022-11-03 12:09:26 +0000
1
/*
2
** Module   : LazyFetching.java
3
** Abstract : A layer between a Query and Results.
4
**
5
** Copyright (c) 2004-2022, Golden Code Development Corporation.
6
**
7
** -#- -I- --Date-- -----------------------------------Description-----------------------------------
8
** 001 RAA 20221010 Added the concept of lazy fetching. This stands between the Query and its Results.
9
*                   If the Query wishes to apply lazy fetching, then this interface needs to be implemented.
10
*                   Implementations might differ, depending on how the results are being retrieved.
11
*                            
12
*/
13

  
14
/*
15
** This program is free software: you can redistribute it and/or modify
16
** it under the terms of the GNU Affero General Public License as
17
** published by the Free Software Foundation, either version 3 of the
18
** License, or (at your option) any later version.
19
**
20
** This program is distributed in the hope that it will be useful,
21
** but WITHOUT ANY WARRANTY; without even the implied warranty of
22
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
** GNU Affero General Public License for more details.
24
**
25
** You may find a copy of the GNU Affero GPL version 3 at the following
26
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
27
** 
28
** Additional terms under GNU Affero GPL version 3 section 7:
29
** 
30
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
31
**   terms apply to the works covered under the License.  These additional terms
32
**   are non-permissive additional terms allowed under Section 7 of the GNU
33
**   Affero GPL version 3 and may not be removed by you.
34
** 
35
**   0. Attribution Requirement.
36
** 
37
**     You must preserve all legal notices or author attributions in the covered
38
**     work or Appropriate Legal Notices displayed by works containing the covered
39
**     work.  You may not remove from the covered work any author or developer
40
**     credit already included within the covered work.
41
** 
42
**   1. No License To Use Trademarks.
43
** 
44
**     This license does not grant any license or rights to use the trademarks
45
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
46
**     of Golden Code Development Corporation. You are not authorized to use the
47
**     name Golden Code, FWD, or the names of any author or contributor, for
48
**     publicity purposes without written authorization.
49
** 
50
**   2. No Misrepresentation of Affiliation.
51
** 
52
**     You may not represent yourself as Golden Code Development Corporation or FWD.
53
** 
54
**     You may not represent yourself for publicity purposes as associated with
55
**     Golden Code Development Corporation, FWD, or any author or contributor to
56
**     the covered work, without written authorization.
57
** 
58
**   3. No Misrepresentation of Source or Origin.
59
** 
60
**     You may not represent the covered work as solely your work.  All modified
61
**     versions of the covered work must be marked in a reasonable way to make it
62
**     clear that the modified work is not originating from Golden Code Development
63
**     Corporation or FWD.  All modified versions must contain the notices of
64
**     attribution required in this license.
65
*/
66

  
67
package com.goldencode.p2j.persist.orm;
68

  
69
import com.goldencode.p2j.persist.*;
70

  
71
/**
72
 * Interface that defines the concept of lazy fetching.
73
 * This process appears between a Query and the retrieval of its Results.
74
 * The interface must be implemented accordingly, depending on the method of retrieving results.
75
 */
76
public interface LazyFetching
77
{
78
   /**
79
    * Method to check if a {@link Record} should be fully/partially fetched or not.
80
    * Fully fetched means that a {@code Record} should be retrieved from the database,
81
    * partially fetched means that a {@code Record} should be retrieved from the cache.
82
    * This method does not make the difference between fully and partially fetching. It only matters if
83
    * the lazy fetching layer is being bypassed or not (what happens after that is not its job).
84
    * 
85
    * @param   comp
86
    *          The number of the {@link QueryComponent} for which we check it's {@link RecordBuffer}.
87
    * @param   id
88
    *          The id of the {@code Record} that is about to be put in the {@code RecordBuffer}.
89
    * @return  {@code true} if a {@code Record} should be fully/partially fetched 
90
    *          (does not matter which one), {@code false} otherwise.
91
    */
92
   public boolean shouldFetch(int comp, Long id);
93
   
94
   /**
95
    * Setter for the {@code oldId}, which is responsible with knowing the id of the
96
    * last {@code Record} that was inside the {@link RecordBuffer}.
97
    * 
98
    * @param   comp
99
    *          The number of the {@link QueryComponent} for which we check it's {@code RecordBuffer}.
100
    * @param   id
101
    *          The id of the old {@code Record}.
102
    */
103
   public void setOldId(int comp, Long id);
104
   
105
   /**
106
    * Method for checking if it is OK to retrieve the full record. Most of the times, the implementation
107
    * of this method will return {@code true}. Only in very few cases, the retrieval of the full record
108
    * will not benefit the cause.
109
    * 
110
    * @return  {@code true} if we are fine with working with the full record, {@code false} otherwise.  
111
    */
112
   public boolean isFullRecordOk();
113
}
new/src/com/goldencode/p2j/persist/orm/ScrollableResults.java 2022-11-09 10:13:03 +0000
8 8
** 001 ECF 20191001 Created initial version, with stubbed methods.
9 9
**     OM  20191111 Added method implementation.
10 10
** 002 SBI 20220811 Added new version of get method to retrieve selected columns from a row.
11
** 003 RAA 20221010 Added a 'get' method with a LazyFetching parameter for when lazy fetching is intended.
11 12
**         20221023 Added a usage of SQLQuery.hydrateRecord(ResultSet, RowStructure, int, Session).
12 13
*/
13 14

  
......
108 109
    * @param   session
109 110
    *          The {@code Session} to be used.
110 111
    */
111
   public ScrollableResults(Statement stmt, ResultSet rs, List<RowStructure> rowStructure, Session session)
112
   public ScrollableResults(Statement stmt, 
113
                            ResultSet rs, 
114
                            List<RowStructure> rowStructure, 
115
                            Session session)
112 116
   {
113 117
      this.stmt = stmt;
114 118
      this.rs = rs;
......
193 197
   }
194 198
   
195 199
   /**
196
    * Obtain the full set of values on current row. An array of primary keys or full {@code Record} will be
197
    * returned.
200
    * Obtain the full set of values on current row. An array of primary keys or full {@code Record}s,  
201
    * or {@code null}s will be returned. First two cases correspond to the need of fetching,
202
    * while {@code null} means that no fetching is necessary for that component.
198 203
    * 
204
    * @param   fetching
205
    *          The instance responsible with lazy fetching.
206
    *          
199 207
    * @return  An array of {@code Object} s if the cursor is on a valid position. Otherwise {@code null} is
200 208
    *          returned. The type of returned elements may be both {@code Long} when an array of PKs (recids)
201 209
    *          is queried or an array of full {@code Record}s. The caller is responsible for handling both
202 210
    *          cases (including hydration, if needed).
203 211
    */
204
   public Object[] get()
212
   public Object[] get(LazyFetching fetching)
205 213
   {
214
      
206 215
      return execute(() ->
207 216
      {
208 217
         int rowSize = (rowStructure == null) ? 0 : rowStructure.size();
......
228 237
            ret = new Object[rowSize];
229 238
            int rsOffset = 1;
230 239
            int recCnt = 0;
240
            
231 241
            for (RowStructure rowStruct : rowStructure)
232 242
            {
233 243
               int expColumnCount = rowStruct.count;
244
               Long object = rs.getLong(rsOffset);
245
 
246
               //if fetching is not null, lazy fetching is intended
247
               if (fetching != null)
248
               {
249
                  if (object != null && !fetching.shouldFetch(recCnt, object))
250
                  {
251
                     ret[recCnt] = null;
252
                     // position on next record
253
                     rsOffset += expColumnCount;
254
                     ++recCnt;
255
                     continue;
256
                  } 
257
               }
258
               
234 259
               try
235 260
               {
236
                  ret[recCnt] =
237
                     SQLQuery.hydrateRecord(rs, rowStruct, rsOffset, session);
261
                  ret[recCnt] = SQLQuery.hydrateRecord(rs, rowStruct, rsOffset, session);
262
                  if (fetching != null)
263
                  {
264
                     fetching.setOldId(recCnt, object);
265
                  }
238 266
               }
239 267
               catch (PersistenceException e)
240 268
               {
......
251 279
   }
252 280
   
253 281
   /**
282
    * Obtain the full set of values on current row. An array of primary keys or full {@code Record} will be
283
    * returned.
284
    * 
285
    * @return  An array of {@code Object} s if the cursor is on a valid position. Otherwise {@code null} is
286
    *          returned. The type of returned elements may be both {@code Long} when an array of PKs (recids)
287
    *          is queried or an array of full {@code Record}s. The caller is responsible for handling both
288
    *          cases (including hydration, if needed).
289
    */
290
   public Object[] get()
291
   {
292
      return get(null);
293
   }
294
   
295
   /**
254 296
    * Obtain the selection of values on current row.
255 297
    * 
256 298
    * @param    dmoInfo