Project

General

Profile

6720_good.patch

Teodor Gorghe, 06/09/2026 03:06 AM

Download (217 KB)

View differences:

new/rules/schema/java_pojo.xml 2026-05-22 13:57:10 +0000
3 3
** Module   : java_dmo.xml
4 4
** Abstract : walks data model AST and generates Java AST for each class node
5 5
**
6
** Copyright (c) 2022-2026, Golden Code Development Corporation.
6
** Copyright (c) 2022, Golden Code Development Corporation.
7 7
**
8 8
** _#_ _I_ __Date__ _______________________________________Description_______________________________________
9 9
** 001 OM  20220707 First commit with basic implementation.
10
** 002 RNC 20260406 Migrate RECID from 32-bit to 64-bit values.
11 10
-->
12 11

  
13 12
<!--
......
113 112
      <rule>typeMapping.put("logical",     "Boolean")</rule>
114 113
      <rule>typeMapping.put("object",      "Long")</rule>
115 114
      <rule>typeMapping.put("raw",         "byte[]")</rule>
116
      <rule>typeMapping.put("recid",       "Long")</rule>
115
      <rule>typeMapping.put("recid",       "Integer")</rule>
117 116
      <rule>typeMapping.put("rowid",       "Long")</rule>
118 117
      
119 118
      <rule>importPacks = create("java.util.HashSet")</rule>
new/rules/schema/p2o.xml 2026-05-22 13:57:10 +0000
312 312
**                           if this is specified in cfg file.
313 313
**     SP  20250324          Removed support for custom denormalized extents.
314 314
** 108 SP  20250714          Fixed column collision check for expanded extent fields.
315
** 109 RNC 20260409          Migrate RECID from 32-bit to 64-bit values.
316 315
-->
317 316

  
318 317
<!--
......
504 503
      <rule>dataTypes.put(prog.field_int64,       'int64'                   )</rule>
505 504
      <rule>dataTypes.put(prog.field_logical,     'logical'                 )</rule>
506 505
      <rule>dataTypes.put(prog.field_raw,         'raw'                     )</rule>
507
      <rule>dataTypes.put(prog.field_recid,       'recid'                   )</rule>
506
      <rule>dataTypes.put(prog.field_recid,       'integer'                 )</rule>
508 507
      <rule>dataTypes.put(prog.field_rowid,       'rowid'                   )</rule>
509 508
      <rule>dataTypes.put(prog.field_class,       'object&lt;? extends _BaseObject_&gt;')</rule>
510 509
      
......
1741 1740
                  <rule>
1742 1741
                     type == prog.field_int or
1743 1742
                     type == prog.field_date or
1743
                     type == prog.field_recid or
1744 1744
                     type == prog.field_handle
1745 1745
                     <action>sqlWidth = #(long) 4</action>
1746 1746
                  </rule>
......
1750 1750
                     <!-- TODO: determine the proper length -->
1751 1751
                     <action>sqlWidth = #(long) -1</action>
1752 1752
                  </rule>
1753
                  <rule>type == prog.field_rowid or
1754
                        type == prog.field_recid
1753
                  <rule>type == prog.field_rowid
1755 1754
                     <action>sqlWidth = #(long) 8</action>
1756 1755
                  </rule>
1757 1756
                  <rule>type == prog.field_char
new/src/com/goldencode/p2j/jmx/FwdServerJMX.java 2026-05-22 13:58:35 +0000
248 248
      OrmDataSetParam,
249 249
      /** Instrumentation for <code>DataSet.createDynamicDataSet</code>. */
250 250
      OrmDynamicDataSetParam,
251
      
252
      /** Lazily hydrated an new record (not rehydrated from cache) */
253
      HydratorNewRecord,
254
      /** Lazily hydrated a record (including rehydration from cache) */
255
      HydratorLazyRecord,
256
      /** Fully or partially hydrated a record, but not lazy */
257
      HydratorNonLazyRecord,
258
      /** The hydrator token matched the result-set token */
259
      HydratorHit,
260
      /** The hydrator token mismatched the result-set token */
261
      HydratorMiss,
262
      /** The hydrator fallbacked to refresh and succeeded */
263
      HyratorSuccessfullRefresh,
264
      /** The hydrator fallbacked to refresh and failed */
265
      HyratorUnsuccessfullRefresh,
266
      /** Created a {@code ScrollableResults} instance with lazy results */
267
      HydratorLazyScrollable,
268
      /** Created a {@code ScrollableResults} instance without lazy results */
269
      HydratorNonLazyScrollable,
270
      /** Executed uniqueResult instance with lazy results */
271
      HydratorLazyUnique,
272
      /** Executed uniqueResult instance without lazy results */
273
      HydratorNonLazyUnique,
251 274

  
252 275
      /** Instrumentation for <code>OutputTableCopier.finished</code> */
253 276
      OutputTableCopier,
......
489 512
   public static enum Counter
490 513
   implements OptionalCounter
491 514
   {
515
      TempTotalFields,
516
      PersistentTotalFields,
517
      TempHydratedRecordsWhenSessionCloses,
518
      PersistentHydratedRecordsWhenSessionCloses,
519
      TempHydratedFieldsWhenSessionCloses,
520
      PersistentHydratedFieldsWhenSessionCloses,
521
      PersistentHydratedFieldsWithLZS,
522
      PersistentHydratedFieldsWithLoader,
523
      TempHydratedFieldsWithLZS,
524
      TempHydratedFieldsWithLoader,
525
      
526
      
527
      /** Lazily hydrated an new record (not rehydrated from cache) */
528
      HydratorNewRecord,
529
      /** Lazily hydrated a record (including rehydration from cache) */
530
      HydratorLazyRecord,
531
      /** Fully or partially hydrated a record, but not lazy */
532
      HydratorNonLazyRecord,
533
      /** The hydrator token matched the result-set token */
534
      HydratorHit,
535
      /** The hydrator token mismatched the result-set token */
536
      HydratorMiss,
537
      /** The hydrator fallbacked to refresh and succeeded */
538
      HyratorSuccessfullRefresh,
539
      /** The hydrator fallbacked to refresh and failed */
540
      HyratorUnsuccessfullRefresh,
541
      /** Created a {@code ScrollableResults} instance with lazy results */
542
      HydratorLazyScrollable,
543
      /** Created a {@code ScrollableResults} instance without lazy results */
544
      HydratorNonLazyScrollable,
545
      /** Executed uniqueResult instance with lazy results */
546
      HydratorLazyUnique,
547
      /** Executed uniqueResult instance without lazy results */
548
      HydratorNonLazyUnique,
549
      
492 550
      /** Incomning network traffic */
493 551
      NetworkReads,
494 552
      /** Outgoing network traffic */
new/src/com/goldencode/p2j/persist/BufferImpl.java 2026-05-22 13:57:10 +0000
1030 1030
    * Get the record ID of the current buffer's current record, if any.  P2J
1031 1031
    * implementation of the RECID function.
1032 1032
    * <p>
1033
    * This method will return a 64-bit recid which represents the internal
1034
    * row ID of the given record.
1033
    * This method will return a 32-bit recid which represents the internal
1034
    * row ID of the given record.  If the actual row ID (which is implemented
1035
    * as a wider integer) cannot fit due to overflow, an error condition will
1036
    * be raised.
1035 1037
    *
1036 1038
    * @return  Record ID of the underlying data record. If no record currently
1037 1039
    *          backs the buffer associated with <code>dmo</code>, a recid
1038 1040
    *          initialized as unknown value is returned.
1041
    * 
1042
    * @throws  ErrorConditionException
1043
    *          if the actual record ID is too wide to fit within a 32-bit
1044
    *          integer.
1039 1045
    */
1040 1046
   public recid recordID()
1041 1047
   {
new/src/com/goldencode/p2j/persist/Cursor.java 2026-05-22 13:57:10 +0000
77 77
**                           account for the case when its state can become invalid. Refs #9402.
78 78
** 032 AL2 20250415          Allow consumers of repositionByID to decide if it should be a scan or not.
79 79
** 033 AL2 20250521          Repositioning to a row is done with NO_LOCK.
80
** 034 RNC 20260401          Modified method 'repositionByID()' to use a 64-bit integer.
81 80
*/
82 81

  
83 82
/*
......
263 262
    * @throws  ErrorConditionException
264 263
    *          if the specified ID represents the unknown value.
265 264
    */
266
   boolean repositionByID(boolean scan, int64 id)
265
   boolean repositionByID(boolean scan, integer id)
267 266
   {
268 267
      Long[] serIDs = new Long[] { id.longValue() };
269 268
      
new/src/com/goldencode/p2j/persist/FqlType.java 2026-05-22 13:57:10 +0000
2 2
** Module   : FqlType.java
3 3
** Abstract : Enumeration of data types for various SQL constructs
4 4
**
5
** Copyright (c) 2004-2026, Golden Code Development Corporation.
5
** Copyright (c) 2004-2020, Golden Code Development Corporation.
6 6
**
7 7
** -#- -I- --Date-- --JPRM-- -----------------------------Description-----------------------------
8 8
** 001 ECF 20080310  @37500  Created initial version. Enumeration of data types for various HQL
......
11 11
** 003 SVL 20120331          Added DATETIME and DATETIMETZ types.
12 12
** 004 OM  20200402          Renamed class to FqlType and move to persist package.
13 13
** 005 IAS 20201123          Added ARRAY type
14
** 006 RNC 20260401          Modified the underlying recid class to use BIGINT instead of INTEGER.
15 14
*/
16 15

  
17 16
/*
......
120 119
      types.put(comhandle.class, Types.VARCHAR);
121 120
      types.put(handle.class   , Types.VARCHAR);
122 121
      types.put(object.class   , Types.VARCHAR);
123
      types.put(recid.class    , Types.BIGINT);
122
      types.put(recid.class    , Types.INTEGER);
124 123
      types.put(rowid.class    , Types.BIGINT);
125 124
*/
126 125
   
new/src/com/goldencode/p2j/persist/Persistence.java 2026-05-22 13:58:35 +0000
751 751
import java.util.function.*;
752 752
import java.util.logging.*;
753 753
import com.goldencode.cache.*;
754
import com.goldencode.p2j.jmx.*;
754 755
import com.goldencode.p2j.persist.deploy.*;
755 756
import com.goldencode.p2j.persist.dialect.*;
756 757
import com.goldencode.p2j.persist.dirty.DirtyShareSupport;
......
1947 1948
      {
1948 1949
         local.closeSession(true);
1949 1950
         ErrorEntry ee = exc.getErrorEntry();
1950
         ErrorManager.recordOrShowError(
1951
                  new int[] {ee.num}, 
1952
                  new String[] {ee.text}, 
1953
                  true, 
1954
                  ee.prefix, 
1955
                  false,
1956
                  false,
1957
                  false,
1958
                  true);
1951
         ErrorManager.recordOrShowError(new int[] {ee.num}, 
1952
                                        new String[] {ee.text},
1953
                                        true,
1954
                                        ee.prefix,
1955
                                        false,
1956
                                        false,
1957
                                        false,
1958
                                        true);
1959 1959
         handleException(ErrorManager.buildErrorText(ee.num, ee.text, ee.prefix, false), exc);
1960 1960
      }
1961 1961
      catch (PersistenceException exc)
......
5248 5248
      /** FQL statement */
5249 5249
      private final String fql;
5250 5250
      
5251
      /** Database dialect */
5252
      private final Dialect dialect;
5253
      
5251 5254
      /** Does the query was generated with maximum results option? */
5252 5255
      private final boolean hasMaxResults;
5253 5256
      
......
5268 5271
       * 
5269 5272
       * @param   hql
5270 5273
       *          FQL statement
5274
       * @param   dialect
5275
       *          Database dialect.
5271 5276
       * @param   maxResults
5272 5277
       *          Maximum results.
5273 5278
       * @param   startOffset
5274 5279
       *          Starting row offset.
5275 5280
       */
5276
      QueryKey(String hql, int maxResults, int startOffset, DataRelation relation, boolean lazyMode)
5281
      QueryKey(String hql, Dialect dialect, int maxResults, int startOffset, DataRelation relation, boolean lazyMode)
5277 5282
      {
5278 5283
         this.fql = hql;
5284
         this.dialect = dialect;
5279 5285
         this.hasMaxResults = maxResults > 0;
5280 5286
         this.hasStartOffset = startOffset > 0;
5281 5287
         this.whereStr = relation == null ? "" : relation.getWhereString().toJavaType();
5282 5288
         this.lazyMode = lazyMode;
5283 5289
         
5284 5290
         int result = 17;
5285
         result = 37 * result + hql.hashCode();
5291
         result = 37 * result + fql.hashCode();
5292
         result = 37 * result + dialect.hashCode();
5286 5293
         result = 37 * result + (hasMaxResults ? 1 : 0) + (hasStartOffset ? 2 : 0);
5287 5294
         result = 37 * result + whereStr.hashCode();
5288 5295
         result = 37 * result + (lazyMode ? 1 : 0);
......
5308 5315
         QueryKey that = (QueryKey) o;
5309 5316
         
5310 5317
         return this.hash == that.hash                     &&
5318
                this.dialect.equals(that.dialect)          &&
5311 5319
                this.hasMaxResults == that.hasMaxResults   &&
5312 5320
                this.hasStartOffset == that.hasStartOffset &&
5313 5321
                this.fql.equals(that.fql) &&
......
5334 5342
      @Override
5335 5343
      public String toString()
5336 5344
      {
5337
         return fql + "[" + hasMaxResults + ":" + hasStartOffset + "];" + whereStr;
5345
         return fql + "[" + hasMaxResults + ":" + hasStartOffset + "] (" + dialect + ") " + whereStr;
5338 5346
      }
5339 5347
   }
5340 5348
   
......
5561 5569
         Query query = null;
5562 5570
         fql = fql.trim(); // just in case
5563 5571
         
5564
         // TODO: use the dialect also? I.e: is it possible to have different SQL for same FQL
5565
         //       if different dialects are used?
5566
         QueryKey key = new QueryKey(fql, maxResults, startOffset, relation, lazyMode);
5572
         QueryKey key = new QueryKey(fql, dialect, maxResults, startOffset, relation, lazyMode);
5567 5573
         
5568
         synchronized (staticQueryCache)
5574
         query = staticQueryCache.get(key);
5575
         if (query == null)
5569 5576
         {
5570
            query = staticQueryCache.get(key);
5571
            if (query == null)
5577
            Consumer<Query> c = (q) ->
5572 5578
            {
5573
               query = Session.createQuery(q ->
5574
               {
5575
                  synchronized (staticQueryCache)
5576
                  {
5577
                     // NOTE: the FQL string is not converted to SQL at this time. The conversion
5578
                     //       is performed once, lazily, when the first navigation is required by a
5579
                     //       call of list(), scroll(), or uniqueResult() on the new query
5580
                     
5581
                     staticQueryCache.put(key, q);
5582
                  }
5583
               },
5584
               fql);
5585
            }
5579
               // NOTE: the FQL string is not converted to SQL at this time. The conversion
5580
               //       is performed once, lazily, when the first navigation is required by a
5581
               //       call of list(), scroll(), or uniqueResult() on the new query
5582
               
5583
               staticQueryCache.put(key, q);
5584
            };
5585
            
5586
            query = Session.createQuery(c, fql);
5586 5587
         }
5587 5588
         
5588 5589
         // update [maxResults] and [startOffset] because the cached query might have set 
......
5979 5980
                  try
5980 5981
                  {
5981 5982
                     session.associate(record);
5983
                     record.refreshHydrator(session);
5982 5984
                  }
5983 5985
                  catch (StaleRecordException exc)
5984 5986
                  {
......
6142 6144
         try
6143 6145
         {
6144 6146
            closingSession = true;
6145
            
6147
            hydrateActiveRecords();
6146 6148
            if (isTransactionOpen())
6147 6149
            {
6148 6150
               if (LOG.isLoggable(Level.WARNING))
......
6221 6223
         }
6222 6224
      }
6223 6225
      
6226
      private void hydrateActiveRecords()
6227
      {
6228
         Iterator<RecordBuffer> iter = bufferManager.activeBuffers(Persistence.this);
6229
         
6230
         Record record;
6231
         
6232
         while (iter.hasNext())
6233
         {
6234
            record = iter.next().getCurrentRecord();
6235
            if (record.primaryKey() < 0)
6236
            {
6237
               continue;
6238
            }
6239
            
6240
            record.hydrateRemainingFields();
6241
         }
6242
      }
6243
      
6224 6244
      /**
6225 6245
       * Notify all registered session listeners that the current ORM session is about to
6226 6246
       * close or the current, implicit transaction is being committed.  Listeners which were set
new/src/com/goldencode/p2j/persist/Record.java 2026-05-22 13:59:11 +0000
2 2
** Module   : Record.java
3 3
** Abstract : The abstract base class for all business data model object classes.
4 4
**
5
** Copyright (c) 2019-2026, Golden Code Development Corporation.
5
** Copyright (c) 2019-2025, Golden Code Development Corporation.
6 6
**
7 7
** -#- -I- --Date-- ---------------------------------------Description---------------------------------------
8 8
** 001 ECF 20191001 Created initial version with basic data and accessors.
......
35 35
** 012 AI  20250625 Added overload of getPropertyValues(boolean).
36 36
** 013 LS  20250523 Changed getPropertyValues() to set the key of the map in a more consistent way for
37 37
**                  denormalized extents.
38
** 014 RNC 20260401 Migrate RECID from 32-bit to 64-bit values.
39 38
*/
40 39

  
41 40
/*
......
102 101
import java.util.*;
103 102
import java.util.function.*;
104 103

  
104
import com.goldencode.p2j.jmx.*;
105 105
import com.goldencode.p2j.oo.lang.BaseObject;
106 106
import com.goldencode.p2j.persist.orm.*;
107 107
import com.goldencode.p2j.util.*;
......
115 115
extends BaseRecord
116 116
implements PropertiesDescriptor
117 117
{
118
   private static final SimpleCounter HYDRATE_RECORDS_WHEN_SESSION_CLOSE =
119
      SimpleCounter.getInstance(FwdServerJMX.Counter.PersistentHydratedRecordsWhenSessionCloses);
120
   
121
   private static final SimpleCounter TOTAL_FIELDS =
122
      SimpleCounter.getInstance(FwdServerJMX.Counter.PersistentTotalFields);
123
   
124
   private static final SimpleCounter HYDRATE_FIELD_WHEN_SESSION_CLOSES =
125
      SimpleCounter.getInstance(FwdServerJMX.Counter.PersistentHydratedFieldsWhenSessionCloses);
126

  
127
   private static final SimpleCounter HYDRATED_FIELDS_LZS =
128
      SimpleCounter.getInstance(FwdServerJMX.Counter.PersistentHydratedFieldsWithLZS);
129
   
130
   private static final SimpleCounter HYDRATED_FIELDS_LOADER =
131
      SimpleCounter.getInstance(FwdServerJMX.Counter.PersistentHydratedFieldsWithLoader);
132
   
118 133
   /**
119 134
    * Default constructor needed by DMOs extending this class.
120 135
    */
......
163 178
   {
164 179
      checkIncomplete(offset);
165 180

  
166
      Integer datum = (Integer) data[offset];
181
      Integer datum = (Integer) getDatum(offset);
167 182
      
168 183
      return datum != null ? new integer(datum) : new integer();
169 184
   }
......
272 287
   {
273 288
      checkIncomplete(offset);
274 289

  
275
      OffsetDateTime datum = (OffsetDateTime) data[offset];
290
      OffsetDateTime datum = (OffsetDateTime) getDatum(offset);
276 291
      
277 292
      return datum != null ? new datetimetz(datum) : new datetimetz();
278 293
   }
......
362 377
      }
363 378
   }
364 379
   
380
   @Override
381
   protected void countHydrateRecordWhenSessionCloses(long count)
382
   {
383
      HYDRATE_RECORDS_WHEN_SESSION_CLOSE.update(count);
384
   }
385
   
386
   @Override
387
   protected void countTotalFields(long count)
388
   {
389
      TOTAL_FIELDS.update(count);
390
   }
391
   
392
   @Override
393
   protected void countHydratedFieldsWithLoader(long count)
394
   {
395
      HYDRATED_FIELDS_LOADER.update(count);
396
   }
397
   
398
   @Override
399
   protected void countHydratedFieldsWithLZS(long count)
400
   {
401
      HYDRATED_FIELDS_LZS.update(count);
402
   }
403
   
404
   @Override
405
   protected void countHydratedFieldWhenSessionCloses(long count)
406
   {
407
      HYDRATE_FIELD_WHEN_SESSION_CLOSES.update(count);
408
   }
409
   
365 410
   /**
366 411
    * Get an {@code datetime} value for the datum at the given offset in the property array.
367 412
    * <p>
......
378 423
   {
379 424
      checkIncomplete(offset);
380 425

  
381
      Timestamp datum = (Timestamp) data[offset];
426
      Timestamp datum = (Timestamp) getDatum(offset);
382 427
      
383 428
      return datum != null ? new datetime(datum) : new datetime();
384 429
   }
......
483 528
   {
484 529
      checkIncomplete(offset);
485 530

  
486
      Date datum = (Date) data[offset];
531
      Date datum = (Date) getDatum(offset);
487 532
      
488 533
      return datum != null ? new date(datum) : new date();
489 534
   }
......
588 633
   {
589 634
      checkIncomplete(offset);
590 635

  
591
      Boolean datum = (Boolean) data[offset];
636
      Boolean datum = (Boolean) getDatum(offset);
592 637
      
593 638
      return datum != null ? new logical(datum) : new logical();
594 639
   }
......
691 736
    */
692 737
   public final int64 _getInt64(int offset)
693 738
   {
694
      Long datum = (Long) data[offset];
739
      checkIncomplete(offset);
740
      
741
      Long datum = (Long) getDatum(offset);
695 742
      
696 743
      return datum != null ? new int64(datum) : new int64();
697 744
   }
......
800 847
   {
801 848
      checkIncomplete(offset);
802 849

  
803
      BigDecimal datum = (BigDecimal) data[offset];
850
      BigDecimal datum = (BigDecimal) getDatum(offset);
804 851
      
805 852
      return datum != null ? new decimal(datum) : new decimal();
806 853
   }
......
917 964
   public final character _getCharacter(int offset)
918 965
   {
919 966
      checkIncomplete(offset);
920

  
921
      String datum = (String) data[offset];
967
      
968
      String datum = (String) getDatum(offset);
922 969
      
923 970
      if (datum != null)
924 971
      {
......
1030 1077
   {
1031 1078
      checkIncomplete(offset);
1032 1079

  
1033
      Long datum = (Long) data[offset];
1080
      Long datum = (Long) getDatum(offset);
1034 1081
      
1035 1082
      return datum != null ? new rowid(datum) : new rowid();
1036 1083
   }
......
1137 1184
   {
1138 1185
      checkIncomplete(offset);
1139 1186

  
1140
      Long datum = (Long) data[offset];
1187
      Long datum = (Long) getDatum(offset);
1141 1188
      
1142 1189
      return datum != null ? handle.fromResourceId(datum, false) : new handle();
1143 1190
   }
......
1244 1291
   {
1245 1292
      checkIncomplete(offset);
1246 1293

  
1247
      Long datum = (Long) data[offset];
1294
      Integer datum = (Integer) getDatum(offset);
1248 1295
      
1249 1296
      return datum != null ? new recid(datum) : new recid();
1250 1297
   }
......
1263 1310
    */
1264 1311
   protected final void _setRecid(int offset, NumberType w)
1265 1312
   {
1266
      Long datum = null;
1313
      Integer datum = null;
1267 1314
      if (w != null && !w.isUnknown())
1268 1315
      {
1269
         datum = w.longValue();
1316
         datum = w.intValue();
1270 1317
      }
1271 1318
      
1272 1319
      setDatum(offset, datum);
......
1350 1397
   {
1351 1398
      checkIncomplete(offset);
1352 1399

  
1353
      byte[] datum = (byte[]) data[offset];
1400
      byte[] datum = (byte[]) getDatum(offset);
1354 1401
      
1355 1402
      return datum != null ? new blob(datum) : new blob();
1356 1403
   }
......
1457 1504
   {
1458 1505
      checkIncomplete(offset);
1459 1506

  
1460
      return new clob((String) data[offset], getCodePage(offset));
1507
      return new clob((String) getDatum(offset), getCodePage(offset));
1461 1508
   }
1462 1509
   
1463 1510
   /**
......
1560 1607
   {
1561 1608
      checkIncomplete(offset);
1562 1609

  
1563
      String datum = (String) data[offset];
1610
      String datum = (String) getDatum(offset);
1564 1611
      
1565 1612
      return datum != null ? comhandle.fromString(datum) : new comhandle();
1566 1613
   }
......
1665 1712
   {
1666 1713
      checkIncomplete(offset);
1667 1714

  
1668
      Long datum = (Long) data[offset];
1715
      Long datum = (Long) getDatum(offset);
1669 1716
      
1670 1717
      // the instance must be typed to Progress.Lang.Object
1671 1718
      object<?> res = new object<>(BaseObject.class);
......
1781 1828
   {
1782 1829
      checkIncomplete(offset);
1783 1830

  
1784
      byte[] datum = (byte[]) data[offset];
1831
      byte[] datum = (byte[]) getDatum(offset);
1785 1832
      
1786 1833
      return datum != null ? new raw(datum) : raw.instantiateUnknownRaw();
1787 1834
   }
......
1956 2003
      RecordMeta meta = _recordMeta();
1957 2004
      if (oneLine)
1958 2005
      {
1959
         int last = data.length;
2006
         int last = getLength();
1960 2007
         int start = (this instanceof TempTableRecord) ? 5 : 0;
1961 2008
         sb.append(meta.legacyName).append('/').append(meta.tables[0]).append(':').append(id).append(" {");
1962 2009
         for (int i = start; i < last; i++)
......
1966 2013
               sb.append(", ");
1967 2014
            }
1968 2015
            
1969
            boolean isChar = data[i] instanceof String;
2016
            boolean isChar = getSimpleDatum(i) instanceof String;
1970 2017
            if (isChar)
1971 2018
            {
1972 2019
               sb.append("\"");
......
1974 2021
            
1975 2022
            boolean incomplete = readFields != null && !readFields.get(i);
1976 2023
            
1977
            sb.append(data[i] == null ? incomplete ? "n/a" : "?" : data[i]);
2024
            Object datum = getSimpleDatum(i);
2025
            sb.append(datum == null ? incomplete ? "n/a" : "?" : datum);
1978 2026
            if (isChar)
1979 2027
            {
1980 2028
               sb.append("\"");
......
1997 2045
            int extent = pms[i].getExtent();
1998 2046
            if (extent == 0)
1999 2047
            {
2000
               sb.append(data[i]);
2048
               sb.append(getSimpleDatum(i));
2001 2049
            }
2002 2050
            else
2003 2051
            {
2004 2052
               for (int k = 0; k < extent; k++)
2005 2053
               {
2006 2054
                  sb.append(k == 0 ? "[" : "");
2007
                  sb.append(data[i + k]);
2055
                  sb.append(getSimpleDatum(i + k));
2008 2056
               }
2009 2057
               
2010 2058
               i += extent - 1;
......
2042 2090
         Object val = properties.get(prop.getLegacyName());
2043 2091
         val = f.apply(prop, val);
2044 2092

  
2093
         Object[] data = getData();
2045 2094
         if (prop.getExtent() > 0)
2046 2095
         {
2047 2096
            for (int j = 0; j < prop.getExtent(); j++, i++)
......
2050 2099
               
2051 2100
               BaseDataType fval = (BaseDataType) Array.get(val, j);
2052 2101
               prop.getDataHandler().setField(data, fval, i, prop);
2102
               setLivePropsAtOffset(i);
2053 2103
            }
2054 2104
         }
2055 2105
         else
2056 2106
         {
2057 2107
            prop.getDataHandler().setField(data, (BaseDataType) val, i, prop);
2108
            setLivePropsAtOffset(i);
2058 2109
         }
2059 2110
      }
2060 2111
   }
......
2127 2178
   }
2128 2179
   
2129 2180
   /**
2130
    * Check if two {@link Record} objects are equal from the point of view of the {@code data} array.
2131
    * <p>
2132
    * <strong>To be noted</strong>, that this method accesses the {@code data} arrays directly without using 
2133
    * any getter. This provides faster access, however should be changed if not all fields are hydrated and
2134
    * access is mandatory from a getter.
2135
    * 
2136
    * @param  otherRecord
2137
    *         The instance to compare against.
2138
    *        
2139
    * @return True if the {@code data} arrays are equal, false - otherwise
2140
    */
2141
   public boolean equalData(Record otherRecord)
2142
   {
2143
      return Arrays.equals(this.data, otherRecord.data);
2144
   }
2145
   
2146
   /**
2147 2181
    * Converts this {@code Record} into a POJO, if POJO class is available.
2148 2182
    * To be implemented by DMO implementations.
2149 2183
    * 
new/src/com/goldencode/p2j/persist/RecordBuffer.java 2026-05-22 13:57:10 +0000
1437 1437
** 412 SP  20251029          Refactor propsMap to use destination as key and source as value.
1438 1438
** 413 TG  20250925          Avoid openScope call for the same buffer in the current scope.
1439 1439
** 414 RNC 20251118          Log DirectAccessException in 'setCurrentRecord()' only if it is not expected.
1440
** 415 AS  20251210          When -rereadfields is active, fully hydrate a record instaead of throwing 8826 error.
1441
** 416 RNC 20260401          Migrate RECID from 32-bit to 64-bit values.
1440
** 415 AS  20251210          When -rereadfields is active, fully hydrate a record instaead of throwing 8826 error. 
1442 1441
*/
1443 1442

  
1444 1443
/*
......
7181 7180
    * Get the record ID of the current buffer's current record, if any.  P2J
7182 7181
    * implementation of the RECID function.
7183 7182
    * <p>
7184
    * This method will return a 64-bit recid which represents the internal
7185
    * row ID of the given record.
7183
    * This method will return a 32-bit recid which represents the internal
7184
    * row ID of the given record.  If the actual row ID (which is implemented
7185
    * as a wider integer) cannot fit due to overflow, an error condition will
7186
    * be raised.
7186 7187
    *
7187 7188
    * @return  Record ID of the underlying data record. If no record currently
7188 7189
    *          backs the buffer associated with <code>dmo</code>, a recid
7189 7190
    *          initialized as unknown value is returned.
7191
    * 
7192
    * @throws  ErrorConditionException
7193
    *          if the actual record ID is too wide to fit within a 32-bit
7194
    *          integer.
7190 7195
    */
7191 7196
   public recid recordID()
7192 7197
   {
7193
      return isAvailable() ? new recid(getCurrentRecord().primaryKey()) : new recid();
7198
      if (isAvailable())
7199
      {
7200
         Record record = getCurrentRecord();
7201
         long id = record.primaryKey();
7202
         if (id < Integer.MIN_VALUE || id > Integer.MAX_VALUE)
7203
         {
7204
            // TODO: don't know what 4GL's overflow behavior is or whether the corresponding
7205
            // error is more serious than an ERROR condition; internally, we support a 64-bit
7206
            // value, but the recid object follows the 32-bit constraint in terms of not
7207
            // formatting this
7208
            txHelper.errHlp.noRecordOrThrowError(
7209
               "Row id of " + id + " is too wide to fit within a 32-bit record ID");
7210
         }
7211
         
7212
         return new recid(id);
7213
      }
7214
      else
7215
      {
7216
         return new recid();
7217
      }
7194 7218
   }
7195 7219
   
7196 7220
   /**
new/src/com/goldencode/p2j/persist/TempRecord.java 2026-05-22 13:58:35 +0000
17 17
** 004 CA  20240918 Removed default methods from interfaces and moved them as concrete implementations, as
18 18
**                  default methods cause the Java metaspace to spike one order of magnitude.
19 19
** 005 AS  20241009 Refactored activeOffset into activeOffsets(Bitset).
20
** 006 AL2 20231102 Added computeIndexForHydrator for lazy hydration.
20 21
*/
21 22

  
22 23
/*
......
74 75

  
75 76
package com.goldencode.p2j.persist;
76 77

  
78
import com.goldencode.p2j.jmx.*;
77 79
import com.goldencode.p2j.persist.orm.*;
78 80
import com.goldencode.p2j.util.object;
79 81

  
......
87 89
extends Record
88 90
implements TempTableRecord
89 91
{
92
   private static final SimpleCounter HYDRATE_RECORDS_WHEN_SESSION_CLOSE =
93
      SimpleCounter.getInstance(FwdServerJMX.Counter.TempHydratedRecordsWhenSessionCloses);
94
   
95
   private static final SimpleCounter TOTAL_FIELDS =
96
      SimpleCounter.getInstance(FwdServerJMX.Counter.TempTotalFields);
97
   
98
   private static final SimpleCounter HYDRATE_FIELD_WHEN_SESSION_CLOSES =
99
      SimpleCounter.getInstance(FwdServerJMX.Counter.TempHydratedFieldsWhenSessionCloses);
100
   
101
   private static final SimpleCounter HYDRATED_FIELDS_LZS =
102
      SimpleCounter.getInstance(FwdServerJMX.Counter.TempHydratedFieldsWithLZS);
103
   
104
   private static final SimpleCounter HYDRATED_FIELDS_LOADER =
105
      SimpleCounter.getInstance(FwdServerJMX.Counter.TempHydratedFieldsWithLoader);
106
   
90 107
   /** The property/column name of "__error-flag__" field. */
91 108
   public static final String _ERROR_FLAG = "_errorFlag";
92 109
   
......
197 214
   @Override
198 215
   public final Long _peerRowid()
199 216
   {
200
      return (Long) data[_PEER_ROWID_DATA_INDEX];
217
      return (Long) getDatum(_PEER_ROWID_DATA_INDEX);
201 218
   }
202 219
   
203 220
   /**
......
237 254
   @Override
238 255
   public final Integer _rowState()
239 256
   {
240
      return (Integer) data[_ROW_STATE_DATA_INDEX];
257
      return (Integer) getDatum(_ROW_STATE_DATA_INDEX);
241 258
   }
242 259
   
243 260
   /**
......
278 295
   @Override
279 296
   public final Long _originRowid()
280 297
   {
281
      return (Long) data[_ORIGIN_ROWID_DATA_INDEX];
298
      return (Long) getDatum(_ORIGIN_ROWID_DATA_INDEX);
282 299
   }
283 300
   
284 301
   /**
......
318 335
   @Override
319 336
   public final Long _datasourceRowid()
320 337
   {
321
      return (Long) data[_DATASOURCE_ROWID_INDEX];
338
      return (Long) getDatum(_DATASOURCE_ROWID_INDEX);
322 339
   }
323 340
   
324 341
   /**
......
356 373
   @Override
357 374
   public final Integer _errorFlags()
358 375
   {
359
      return (Integer) data[_ERROR_FLAG_DATA_INDEX];
376
      return (Integer) getDatum(_ERROR_FLAG_DATA_INDEX);
360 377
   }
361 378
   
362 379
   /**
......
392 409
   @Override
393 410
   public final String _errorString()
394 411
   {
395
      return (String) data[_ERROR_STRING_DATA_INDEX];
412
      return (String) getDatum(_ERROR_STRING_DATA_INDEX);
396 413
   }
397 414
   
398 415
   /**
......
507 524
      Class<?> implIFace = _recordMeta().getDmoMeta().getAnnotatedInterface();
508 525
      TemporaryBuffer.updateObjectRefCount(implIFace, oldVal, newVal);
509 526
   }
527
   
528
   @Override
529
   protected int getHydratorRowOffset()
530
   {
531
      return 2;
532
   }
533
   
534
   @Override
535
   protected void countHydrateRecordWhenSessionCloses(long count)
536
   {
537
      HYDRATE_RECORDS_WHEN_SESSION_CLOSE.update(count);
538
   }
539
   
540
   @Override
541
   protected void countTotalFields(long count)
542
   {
543
      TOTAL_FIELDS.update(count);
544
   }
545
   
546
   @Override
547
   protected void countHydratedFieldsWithLZS(long count)
548
   {
549
      HYDRATED_FIELDS_LZS.update(count);
550
   }
551
   
552
   @Override
553
   protected void countHydratedFieldsWithLoader(long count)
554
   {
555
      HYDRATED_FIELDS_LOADER.update(count);
556
   }
557
   
558
   @Override
559
   protected void countHydratedFieldWhenSessionCloses(long count)
560
   {
561
      HYDRATE_FIELD_WHEN_SESSION_CLOSES.update(count);
562
   }
510 563
}
new/src/com/goldencode/p2j/persist/dialect/Dialect.java 2026-05-22 13:58:35 +0000
605 605
   }
606 606
   
607 607
   /**
608
    * Create the error descriptor from the SQLException message.
609
    *
608
    * Create the error descriptor from the {@code SQLException} message.
609
    * 
610 610
    * @param   message
611 611
    *          The SQLException message.
612 612
    *
......
620 620
   /**
621 621
    * Check if Common Table Expressions should be used for converted CONTAINS operator
622 622
    * 
623
    * @return <code>true</code> if Common Table Expressions should be used for converted CONTAINS operator
623
    * @return  <code>true</code> if Common Table Expressions should be used for converted CONTAINS operator
624 624
    */
625 625
   public boolean useCTE4Contains()
626 626
   {
......
718 718
   public abstract void generateWordTablesDDLImpl(String dbName,
719 719
                                                  PrintStream out,
720 720
                                                  String eoln,
721
                                                  Collection<WordTable>  wordTables);
721
                                                  Collection<WordTable> wordTables);
722 722
   
723 723
   /**
724 724
    * Create a data object, the purpose of which is specific to a particular
......
2189 2189
   {
2190 2190
      return null;
2191 2191
   }
2192

  
2193
   /**
2194
    * Indicate whether this dialect is likely to benefit from lazy hydration of DMOs when reading a record
2195
    * from the database. This serves as a hint, but may be overridden by configuration or runtime conditions.
2196
    * 
2197
    * @return  {@code true} unless overridden by subclasses.
2198
    */
2199
   public boolean useLazyHydration()
2200
   {
2201
      return true;
2202
   }
2192 2203
   
2193 2204
   /**
2194 2205
    * Use the provided database connection to extract the collation used by the database and report it
new/src/com/goldencode/p2j/persist/dialect/H2Helper.java 2026-05-22 13:58:35 +0000
129 129
import com.goldencode.p2j.directory.*;
130 130
import com.goldencode.p2j.persist.*;
131 131
import com.goldencode.p2j.persist.Database;
132
import com.goldencode.p2j.persist.dialect.*;
132 133
import com.goldencode.p2j.persist.orm.*;
133 134
import com.goldencode.p2j.persist.orm.Session;
134 135
import com.goldencode.p2j.persist.pl.*;
new/src/com/goldencode/p2j/persist/dialect/P2JH2Dialect.java 2026-05-22 13:57:10 +0000
145 145
** 054 OM  20250701          Multiple signatures changes in super class.
146 146
** 055 OM  20250718          Added new method: isSequenceMissing(Throwable).
147 147
** 056 OM  20250731          Dropped dead code related to old technology no longer in use.
148
**     ES  20250805          Inject computed __null column in orderBy clause.
149
** 057 RNC 20260401          Migrate RECID from 32-bit to 64-bit values.
148
**     ES  20250805          Inject computed __null column in orderBy clause. 
150 149
*/
151 150

  
152 151
/*
......
258 257
   {
259 258
      fwd2sql.put("integer",    "integer");
260 259
      fwd2sql.put("Integer",    "integer");
261
      fwd2sql.put("recid",      "bigint");
260
      fwd2sql.put("recid",      "integer");
262 261
      fwd2sql.put("int64",      "bigint");
263 262
      fwd2sql.put("Long",       "bigint");
264 263
      fwd2sql.put("rowid",      "bigint");
new/src/com/goldencode/p2j/persist/dialect/P2JPostgreSQLDialect.java 2026-05-22 13:57:10 +0000
148 148
** 061 OM  20250718          Added new method: isSequenceMissing(Throwable).
149 149
** 062 OM  20250731          Dropped dead code related to old technology no longer in use.
150 150
** 063 OM  20250922          Simplified MSSQL indexes.
151
** 064 RNC 20260401          Migrate RECID from 32-bit to 64-bit values.
152 151
*/
153 152

  
154 153
/*
......
396 395
   {
397 396
      fwd2sql.put("integer",    "int4");
398 397
      fwd2sql.put("Integer",    "int4");
399
      fwd2sql.put("recid",      "int8");
398
      fwd2sql.put("recid",      "int4");
400 399
      fwd2sql.put("int64",      "int8");
401 400
      fwd2sql.put("Long",       "int8");
402 401
      fwd2sql.put("rowid",      "int8");
new/src/com/goldencode/p2j/persist/dialect/P2JSQLServer2012Dialect.java 2026-05-22 13:57:10 +0000
33 33
** 013 ES  20250827 Make direction of the primary key to always use ascendent direction.
34 34
** 014 OM  20250918 Droped NULL components from indexes. Added PK for unique indexes.
35 35
** 015 RNC 20260127 Added SQLSERVER_LIKE_PATTERN_OPERATORS.
36
** 016 RNC 20260401 Migrate RECID from 32-bit to 64-bit values.
37 36
*/
38 37

  
39 38
/*
......
239 238
      indexFieldSizes.put(integer.class,     4); // int
240 239
      indexFieldSizes.put(logical.class,     1); // bit
241 240
      indexFieldSizes.put(int64.class,       8); // bigint
242
      indexFieldSizes.put(recid.class,       8); // bigint
241
      indexFieldSizes.put(recid.class,       4); // int
243 242
      indexFieldSizes.put(datetimetz.class, 10); // datetimeoffset
244 243
      indexFieldSizes.put(datetime.class,    8); // datetime2
245 244
      indexFieldSizes.put(date.class,        3); // date
......
253 252
      
254 253
      fwd2sql.put("integer",    "int");
255 254
      fwd2sql.put("Integer",    "int");
256
      fwd2sql.put("recid",      "bigint");
255
      fwd2sql.put("recid",      "int");
257 256
      fwd2sql.put("int64",      "bigint");
258 257
      fwd2sql.put("Long",       "bigint");
259 258
      fwd2sql.put("rowid",      "bigint");
new/src/com/goldencode/p2j/persist/dirty/DefaultDirtyShareManager.java 2026-05-22 13:58:35 +0000
834 834
               indexUpdateStates.remove(ident);
835 835
            }
836 836
            
837
            String hql = "delete from " + entity + 
838
                         " where " + DatabaseManager.PRIMARY_KEY + " = ?";
837
            String fql = "delete from " + entity + " where " + Session.PK + " = ?";
839 838
            Session session = null;
840 839
            boolean inTx = false;
841 840
            
......
843 842
            {
844 843
               session = new Session(dirtyDatabase);
845 844
               inTx = session.beginTransaction();
846
               Query query = Session.createQuery(hql);
845
               Query query = Session.createQuery(fql);
847 846
               query.setParameter(0, id);
848 847
               query.executeUpdate(session);
849 848
               session.commit();
......
1223 1222
   }
1224 1223
   
1225 1224
   /**
1226
    * Execute an HQL query and return the results as a list. If the query returns multiple results
1225
    * Execute an FQL query and return the results as a list. If the query returns multiple results
1227 1226
    * per row, each element in the list will be an array of {@code Object}s.
1228 1227
    * <p>
1229 1228
    * No locking is attempted.
new/src/com/goldencode/p2j/persist/hql/DataTypeHelper.java 2026-05-22 13:57:10 +0000
45 45
** 026 SP  20240516          Process the function name in getTypeFunction() when there is an underscore
46 46
** 027 CA  20241107          Added character constant support.
47 47
** 028 ICP 20250123          Added support for integer and int64 constants.
48
** 029 RNC 20260401          Migrate RECID from 32-bit to 64-bit values.
49 48
*/
50 49

  
51 50
/*
......
561 560
      // P2J wrapper types.
562 561
      classes.put(logical.class    , FqlType.BOOLEAN);
563 562
      classes.put(integer.class    , FqlType.INTEGER);
564
      classes.put(recid.class      , FqlType.LONG);
563
      classes.put(recid.class      , FqlType.INTEGER);
565 564
      classes.put(decimal.class    , FqlType.DECIMAL);
566 565
      classes.put(date.class       , FqlType.DATE);
567 566
      classes.put(raw.class        , FqlType.RAW);
new/src/com/goldencode/p2j/persist/meta/MetadataManager.java 2026-05-22 13:57:10 +0000
73 73
** 032 OM  20250331 Make sure the [byName] map's keys are in lowercase. Avoid possible duplication of default
74 74
**                  tenant record in _tenant meta table.
75 75
** 033 SP  20250321 Removed support for custom denormalized extents.
76
** 034 RNC 20260401 Migrate RECID from 32-bit to 64-bit values.
77 76
*/
78 77

  
79 78
/*
......
215 214
   private static final boolean LOG_INFO = log.isLoggable(Level.INFO);
216 215
   
217 216
   /** The recid of the database in {@code _Db} table. */
218
   private static final long DB_RECID = 4032;
217
   private static final int DB_RECID = 4032;
219 218
   
220 219
   /** Map of data type names to associated _Field._dtype value */
221 220
   private static final Map<String, Integer> DTYPE = Collections.unmodifiableMap(
......
252 251
            put("logical", "bit");
253 252
            put("integer", "integer");
254 253
            put("decimal", "numetic");
255
            put("recid", "bigint");
254
            put("recid", "integer");
256 255
            put("raw", "varbinary");
257 256
            put("blob", "varbinary");
258 257
            put("clob", "varchar");
......
825 824
         // extract the list of indices of this table ...
826 825
         PreparedStatement stmt = conn.prepareStatement(
827 826
               "select " + Session.PK + " from meta_index where file_recid=?");
828
         stmt.setLong(1, fileNum2);
827
         stmt.setLong(1, (long) fileNum2);
829 828
         ResultSet rs = stmt.executeQuery();
830 829
         while (rs.next())
831 830
         {
832 831
            // ... and drop their index components
833
            deleteRecord(conn,
834
                         rs.getLong(1),
835
                         "delete from meta_index_field where index_recid=?",
836
                         "index components");
832
            deleteRecord(
833
                  conn, rs.getInt(1), "delete from meta_index_field where index_recid=?", "index components");
837 834
         }
838 835
         rs.close();
839 836
         stmt.close();
840 837
         
841 838
         // then, delete them from _Index
842
         deleteRecord(conn, fileNum2, "delete from meta_index where file_recid=?", "indices");
839
         deleteRecord(conn, (long) fileNum2, "delete from meta_index where file_recid=?", "indices");
843 840
         
844 841
         // next, delete from _Field
845
         deleteRecord(conn, fileNum2, "delete from meta_field where file_recid=?", "fields");
842
         deleteRecord(conn, (long) fileNum2, "delete from meta_field where file_recid=?", "fields");
846 843
         
847 844
         // finally, delete from _File
848
         deleteRecord(conn, fileNum2, "delete from meta_file where " + Session.PK + "=?", "tables");
845
         deleteRecord(conn, (long) fileNum2, "delete from meta_file where " + Session.PK + "=?", "tables");
849 846
         
850 847
         if (inTx)
851 848
         {
......
999 996
      }
1000 997
      
1001 998
      long fileNum = nextId(meta, SystemTable._File.fileName);
1002
      int64 pk = new int64();
999
      integer pk = new integer();
1003 1000
      Map<SystemTable, List<Map<Tuple<String, Integer>, Object>>> children =
1004
            childData(meta, dmoIface, fileNum, pk);
1001
            childData(meta, dmoIface, (int)fileNum, pk);
1005 1002
      setMetaTableRecord(p, fileHelper,
1006 1003
            new FileTableRecordBuilder()
1007 1004
                  .put(Session.PK, fileNum)
1008 1005
                  .put("fileNumber", integer.of(fileNum))
1009
                  .put("template", int64.of(-fileNum))
1006
                  .put("template", integer.of(-fileNum))
1010 1007
                  .put("tblType", character.of("T"))
1011 1008
                  .build(dmoIface, pk, children)
1012 1009
      );
1013 1010
      templateRecords.put(dmoImpl, -fileNum);
1014 1011
      FILE_NUM.computeIfAbsent(primary, d -> new ConcurrentHashMap<>()).
1015
            putIfAbsent(dmoImpl, integer.of((int) fileNum));
1012
            putIfAbsent(dmoImpl, new integer(fileNum));
1016 1013
      FILE_NUM_BY_TBL_NAME.computeIfAbsent(primary, d -> new ConcurrentHashMap<>()).
1017
            putIfAbsent(dmoIface.getAnnotation(Table.class).name(), (int) fileNum);
1014
            putIfAbsent(dmoIface.getAnnotation(Table.class).name(), (int)fileNum);
1018 1015
      saveChildren(p, children);
1019 1016
      
1020 1017
      if ((isDynamic && LOG_INFO) || log.isLoggable(Level.FINE))
......
1081 1078
         return false;
1082 1079
      }
1083 1080
      
1084
      int64 pk = new int64();
1081
      integer pk = new integer();
1085 1082
      Map<SystemTable, List<Map<Tuple<String, Integer>, Object>>> children = childData(
1086 1083
            metaDb, dmoIface, systemTable.fileNum, pk);
1087 1084
      long id = nextId(metaDb, SystemTable._File.fileName);
1088

  
1085
      
1089 1086
      setMetaTableRecord(p, fileHelper,
1090 1087
            new FileTableRecordBuilder()
1091 1088
                  .put(Session.PK, id)
1092
                  .put("fileNumber", integer.of(systemTable.fileNum))
1093
                  .put("template", int64.of(-id))
1089
                  .put("fileNumber", new integer(systemTable.fileNum))
1090
                  .put("template", new integer(-id))
1094 1091
                  .put("tblType", new character("S"))
1095 1092
                  .build(dmoIface, pk, children)
1096 1093
      );
......
1188 1185
                  new MapBuilder<>().
1189 1186
                     put(Session.PK, nextId).
1190 1187
                     put("seqName", new character(seq.legacy())).
1191
                     put("seqInit", int64.of(seq.start())).
1192
                     put("seqIncr", int64.of(seq.increment())).
1193
                     put("seqMin", int64.of(seq.minValue())).
1194
                     put("seqMax",int64.of(seq.maxValue())).
1188
                     put("seqInit", new int64(seq.start())).
1189
                     put("seqIncr", new int64(seq.increment())).
1190
                     put("seqMin", new int64(seq.minValue())).
1191
                     put("seqMax",new int64(seq.maxValue())).
1195 1192
                     put("cycleOk",new logical(seq.cycle())).
1196 1193
                     put("dbRecid",new recid(nextId)).
1197
                     build()
1194
                  build()
1198 1195
            );
1199 1196
         }
1200 1197
      } catch (NoSuchMethodException | SecurityException | 
......
1281 1278
      
1282 1279
      setMetaTableRecord(p, h,
1283 1280
            new MapBuilder<>()
1284
                  .put(Session.PK, DB_RECID)
1281
                  .put(Session.PK, (long) DB_RECID)
1285 1282
                  .put("dbName",  new character("_meta"))
1286 1283
                  .put("dbType",  new character(""))
1287 1284
                  .put("dbComm",  new character(""))
......
1910 1907
   private static Map<SystemTable, List<Map<Tuple<String, Integer>, Object>>> childData(
1911 1908
             Database metaDb,
1912 1909
             Class<? extends DataModelObject> dmoIface,
1913
             long _file_num,
1914
             int64 pk)
1910
             int _file_num,
1911
             integer pk)
1915 1912
   {
1916 1913
      Map<SystemTable, List<Map<Tuple<String, Integer>, Object>>> children = new EnumMap<>(SystemTable.class);
1917 1914
      List<Map<Tuple<String, Integer>, Object>> fields = new LinkedList<>();
......
1919 1916
      List<Map<Tuple<String, Integer>, Object>> indexFields = new LinkedList<>();
1920 1917
      List<Map<Tuple<String, Integer>, Object>> fileTriggers = new LinkedList<>();
1921 1918
      List<Map<Tuple<String, Integer>, Object>> fieldTriggers = new LinkedList<>();
1922
      Map<String, int64> fieldRecidByName = new LinkedHashMap<>();
1919
      Map<String, integer> fieldRecidByName = new LinkedHashMap<>();
1923 1920
      Map<String, integer> fieldRposByName = new LinkedHashMap<>();
1924 1921
      children.put(SystemTable._Field, fields);
1925 1922
      children.put(SystemTable._Index, indexes);
......
1946 1943
         String field = trigger.field();
1947 1944
         if (!field.isEmpty())
1948 1945
         {
1949
            int64 fieldRecId = fieldRecidByName.get(field);
1946
            integer fieldRecId = fieldRecidByName.get(field);
1950 1947
            integer fieldRpos = fieldRposByName.get(field);
1951 1948
            if (fieldRecId == null || fieldRpos == null)
1952 1949
            {
......
1962 1959
                  new MapBuilder<>().
1963 1960
                  put(Session.PK, nextId(metaDb, SystemTable._Field_Trig.fileName)).
1964 1961
                  put("fieldRecid", fieldRecId).
1965
                  put("fileRecid", int64.of(_file_num)).
1962
                  put("fileRecid", integer.of(_file_num)).
1966 1963
                  put("fieldRpos", fieldRpos).
1967 1964
                  put("event", new character(trigger.event())).
1968 1965
                  put("procName", new character(trigger.procedure())).
......
1975 1972
            fileTriggers.add(
1976 1973
                  new MapBuilder<>().
1977 1974
                  put(Session.PK, nextId(metaDb, SystemTable._File_Trig.fileName)).
1978
                  put("fileRecid", int64.of(_file_num)).
1975
                  put("fileRecid", integer.of(_file_num)).
1979 1976
                  put("event", new character(trigger.event())).
1980 1977
                  put("procName", new character(trigger.procedure())).
1981 1978
                  put("override", logical.of(trigger.overridable())).
......
2008 2005
    */
2009 2006
   private static void indexData(Database metaDb,
2010 2007
                                 String tblDmoName,
2011
                                 long _file_num,
2008
                                 int _file_num,
2012 2009
                                 Iterator<P2JIndex> indices,
2013
                                 int64 pk,
2010
                                 integer pk,
2014 2011
                                 List<Map<Tuple<String, Integer>, Object>> indexes,
2015 2012
                                 List<Map<Tuple<String, Integer>, Object>> indexFields,
2016
                                 Map<String, int64> fieldRecidByName)
2013
                                 Map<String, integer> fieldRecidByName)
2017 2014
   {
2018 2015
      while (indices.hasNext())
2019 2016
      {
......
2021 2018
         long id = nextId(metaDb, SystemTable._Index.fileName);
2022 2019
         if (idx.isPrimary())
2023 2020
         {
2024
            pk.assign(int64.of(id));
2021
            pk.assign(integer.of(id));
2025 2022
         }
2026 2023
         indexes.add(new MapBuilder<>().
2027 2024
               put(Session.PK, id).
2028
               put("fileRecid", int64.of(_file_num)).
2025
               put("fileRecid", integer.of(_file_num)).
2029 2026
               put("indexName", new character(idx.getName())).
2030 2027
               put("unique", logical.of(idx.isUnique())).
2031 2028
               build()
......
2036 2033
         {
2037 2034
            P2JIndexComponent fld = comps.get(i);
2038 2035
            String compName = fld.getPropertyName();
2039
            int64 fieldRecid = fieldRecidByName.get(compName);
2036
            integer fieldRecid = fieldRecidByName.get(compName);
2040 2037
            
2041 2038
            if (fieldRecid == null)
2042 2039
            {
......
2045 2042
            }
2046 2043
            indexFields.add(new MapBuilder<>().
2047 2044
                  put(Session.PK, nextId(metaDb, SystemTable._Index_Field.fileName)).
2048
                  put("indexRecid", int64.of(id)).
2049
                  put("fieldRecid", fieldRecidByName.getOrDefault(compName, int64.UNKNOWN)).
2045
                  put("indexRecid", integer.of(id)).
2046
                  put("fieldRecid", fieldRecidByName.getOrDefault(compName, integer.UNKNOWN)).
2050 2047
                  put("indexSeq", integer.of(seqNo++)).
2051 2048
                  build()
2052 2049
            );
......
2072 2069
    * @return _Field table data for a DMO field.
2073 2070
    */
2074 2071
   private static Map<Tuple<String, Integer>, Object> fieldData(Database metaDb,
2075
                                                                long _file_num,
2072
                                                                int _file_num,
2076 2073
                                                                Property property,
2077 2074
                                                                Class<?> ftype,
2078
                                                                Map<String, int64> fieldRecidByName,
2075
                                                                Map<String, integer> fieldRecidByName,
2079 2076
                                                                Map<String, integer> fieldRposByName)
2080 2077
   {
2081 2078
      long id = nextId(metaDb, SystemTable._Field.fileName);
2082
      fieldRecidByName.put(property.name, int64.of(id));
2079
      fieldRecidByName.put(property.name, new integer(id));
2083 2080
      fieldRposByName.put(property.name, integer.of(property.order));
2084 2081
      int  wd = property.width;
2085 2082
      integer width = wd >= 0 ? integer.of(wd) : integer.UNKNOWN;
......
2090 2087
      String collation =  charField ? (caseSensitive ? "basic_S" : "basic_I") : null;
2091 2088
      return new MapBuilder<>().
2092 2089
            put(Session.PK, id).
2093
            put("fileRecid", int64.of(_file_num)).
2090
            put("fileRecid", integer.of(_file_num)).
2094 2091
            put("fieldName", new character(property.legacy)).
2095 2092
            put("dataType", character.of(typeName)).
2096 2093
            put("mandatory", logical.of(property.mandatory)).
......
2739 2736
       */
2740 2737
      public Map<Tuple<String, Integer>, Object> build(
2741 2738
            Class<? extends DataModelObject> dmoIface,
2742
            int64 pk,
2739
            integer pk,
2743 2740
            Map<SystemTable, List<Map<Tuple<String, Integer>, Object>>> children)
2744 2741
      {
2745 2742
         Table table = dmoIface.getAnnotation(Table.class);
2746 2743
         int numfld = children.get(SystemTable._Field).size();
2747 2744
         
2748
         return put("dbRecid", int64.of(DB_RECID)).
2745
         return put("dbRecid", integer.of(DB_RECID)).
2749 2746
                put("fileName", new character(table.legacy())).
2750 2747
                put("owner", character.of("PUB")).
2751 2748
                put("userMisc", new character(table.name())).
new/src/com/goldencode/p2j/persist/orm/AbstractRowStructure.java 2026-05-22 13:58:35 +0000
12 12
** 003 LS  20241105 Added hasOnlyPK().
13 13
** 004 OM  20240701 Replaced + concatenation with append in StringBuilder.
14 14
**     SP  20250321 Removed usage of prop.index.
15
** 005 AL2 20231214 Fixed hydrate extents to avoid honoring recOffset if set on -1.
15 16
*/
16 17

  
17 18
/*
......
177 178
    * @throws  PersistenceException
178 179
    *          thrown when hydrating extents fails (as it requires extra SQL queries to be run).
179 180
    */
180
   protected void hydrateExtents(Session session, BaseRecord r, int recOffset)
181
   @Override
182
   public void hydrateExtents(Session session, BaseRecord r, int recOffset)
181 183
   throws PersistenceException
182 184
   {
183 185
      // TODO: collect extent properties and do a new query from SQL, see Loader.readExtentData()
......
188 190
         PropertyMeta[] propsMeta = recordMeta.getPropertyMeta(false);
189 191
         String[] loadSqls = recordMeta.loadSql;
190 192
         int[] loadSqlsIndexes = recordMeta.loadSqlIndexes;
191
         boolean incomplete = isIncomplete();
193
         boolean arbitrary = isIncomplete() || recOffset == -1;
192 194
         
193 195
         // only use the extent queries, skip the loadSqls[0] which contains the simple properties
194 196
         for (int i = 1; i < loadSqls.length; i++) // skip "plain" columns 
195 197
         {            
196
            if (incomplete)
198
            if (arbitrary)
197 199
            {
198 200
               // resolve the offset in the 'props' array where this sql starts.  
199 201
               // all non-expanded extent fields are loaded even for incomplete records.
new/src/com/goldencode/p2j/persist/orm/AdaptiveRowStructure.java 2026-05-22 13:58:35 +0000
10 10
**     AL2 20231212 Use dmoMeta directly, without getter.
11 11
** 002 OM  20240715 Fixed copy/paste bug.
12 12
** 003 LS  20250714 Added 'getNeededFields' implementation.
13
** 004 AL2 20231214 Added implementation for hydrateAt.
13 14
*/
14 15

  
15 16
/*
......
69 70

  
70 71
import java.sql.ResultSet;
71 72
import java.sql.SQLException;
72
import java.util.BitSet;
73
import java.util.Iterator;
73
import java.util.*;
74 74

  
75 75
import com.goldencode.p2j.persist.*;
76 76

  
......
228 228
      return delegate.getNeededFields();
229 229
   }
230 230

  
231

  
232
   /**
233
    * Hydrate only one property in the base-record. This is largely used by the lazy hydrator,
234
    * allowing it to hydrate only the property that is accessed now. The other hydration method 
235
    * ({@link #hydrate}) eagerly hydrates all properties, is a slow process and may do useless
236
    * hydrations on properties that are not accessed.
237
    * 
238
    * @param   resultSet
239
    *          The ResultSet from which the hydration should be done
240
    * @param   rsOffset
241
    *          The result set offset from which the reading should be done. This is relevant as
242
    *          the result set may contain a joined row, but we are interested only in a specific
243
    *          record that may start at a specific offset.
244
    * @param   r
245
    *          The record that should be hydrated. 
246
    * @param   propOffset
247
    *          The property that should be hydrated. The caller is responsible in assuring that
248
    *          this property wasn't hydrated before.
249
    * 
250
    * @return  {@code true} if this worked due to the fact that it was a scalar value. {@code false}
251
    *          in case the property was a non-expanded 
252
    *          
253
    * @throws  PersistenceException
254
    *          This is thrown when reading the scalar property fails.
255
    */
256
   @Override
257
   public boolean hydrateAt(ResultSet resultSet, int rsOffset, BaseRecord r, int dataIndex)
258
   throws PersistenceException
259
   {
260
      return delegate.hydrateAt(resultSet, rsOffset, r, dataIndex);
261
   }
262
   
263
   /**
264
    * Retrieve the fields that were loaded from the database.
265
    *
266
    * @return A BitSet object, where true means that the field associated with that position in the {@code
267
    * data} array has been loaded from database, and false - otherwise.
268
    */
269
   @Override
270
   public BitSet getLoadedFields()
271
   {
... This diff was truncated because it exceeds the maximum size that can be displayed.