Project

General

Profile

Feature #2376

retain bulk getter/setter methods for custom denormalized extent fields

Added by Eric Faulhaber over 9 years ago. Updated about 8 years ago.

Status:
Test
Priority:
Normal
Assignee:
-
Target version:
-
Start date:
Due date:
% Done:

0%

billable:
No
vendor_id:
GCD

Related issues

Related to Database - Feature #2134: configurable denormalization of extent fields into individual fields in schema conversion Closed 08/13/2013 08/23/2013

History

#1 Updated by Eric Faulhaber over 9 years ago

There appears is a hole in our current implementation of custom, denormalized extent fields, in that we have eliminated the "bulk" getter and setter methods from our DMO interface and implementation classes when using custom schema hints to denormalize extent fields (see #2134).

An example of a bulk getter from the p2j_test.Person table:

public integer[] getHours();

An example of a bulk setter from the p2j_test.Person table:

public void setHours(NumberType[] elements);

These need to be retained in the DMO interface and handled specially in the RecordBuffer$Handler invocation handler. The implementation of these methods in the DMO implementation class should throw UnsupportedOperationException, since they should not be invoked directly.

This will cover cases of converted code where the "bulk" convenience syntax is used in application code, since the existing form of conversion (i.e., calling the bulk getter/setter) is more elegant and preferable to exploding out converted code into multiple method calls or a loop.

#2 Updated by Vadim Nebogatov over 9 years ago

Test testcases/uast/denormalization/bulk1:

def buffer b for person.
def var hBuffer as handle.
hBuffer = buffer b:handle.

hBuffer:FIND-FIRST.
MESSAGE hBuffer:BUFFER-FIELD("hours"):BUFFER-VALUE().
MESSAGE hBuffer:BUFFER-FIELD("hours"):BUFFER-VALUE(1).
MESSAGE hBuffer:BUFFER-FIELD("hours"):BUFFER-VALUE(2).
MESSAGE hBuffer:BUFFER-FIELD("hours"):BUFFER-VALUE(3).
MESSAGE hBuffer:BUFFER-FIELD("hours"):BUFFER-VALUE(4).

Progress results:

?
0
14
17
0

P2J with hints file

<hints>
   <schema>

      <!-- custom-extent hint for all extent fields in table -->
      <table name="vehicle">
         <custom-extent/>
      </table>

      <!-- custom-extent hints for concrete fields-->
      <table name="person">
         <custom-extent>

            <!-- configurable naming conversion -->

            <field name="schedule">
               <extent-field name = "schedule2" label = "label of schedule2 text"/>
               <extent-field name = "schedule1" description = "description of schedule1 text"/>
               <extent-field name = "scheduleThird" label = "label of scheduleThird text" description = "description of scheduleThird text"/>
               <extent-field name = "scheduleFourth"/>
               <extent-field name = "scheduleFifth"/>
            </field>

            <!-- default naming conversion-->

            <field name="hours"/>

            <!-- default naming conversion-->
            <field name="extension"/>

            <!-- no naming conversion -->
            <!-- <field name="email"/> -->
         </custom-extent>
      </table>
   </schema>
</hints>

gives exception in method fetchIndexedPropertyMethods(...) as was discussed in emails:

[08/14/2014 23:29:08 MSK] (com.goldencode.p2j.persist.DynamicQueryHelper:SEVERE) Could not instantiate the P2JQuery for the '' predicate for query find_FIRST_SHARE
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.goldencode.p2j.persist.DynamicQueryHelper.compileQuery(DynamicQueryHelper.java:872)
        at com.goldencode.p2j.persist.DynamicQueryHelper.parse(DynamicQueryHelper.java:288)
        at com.goldencode.p2j.persist.DynamicQueryHelper.parseFindQuery(DynamicQueryHelper.java:475)
        at com.goldencode.p2j.persist.BufferImpl._find(BufferImpl.java:2861)
        at com.goldencode.p2j.persist.BufferImpl.findFirst(BufferImpl.java:1812)
        at com.goldencode.testcases.Test$1.body(Test.java:41)
        at com.goldencode.p2j.util.BlockManager.processBody(BlockManager.java:7048)
        at com.goldencode.p2j.util.BlockManager.topLevelBlock(BlockManager.java:6881)
        at com.goldencode.p2j.util.BlockManager.externalProcedure(BlockManager.java:221)
        at com.goldencode.p2j.util.BlockManager.externalProcedure(BlockManager.java:203)
        at com.goldencode.testcases.Test.execute(Test.java:28)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.goldencode.p2j.util.Utils.invoke(Utils.java:1238)
        at com.goldencode.p2j.main.StandardServer$MainInvoker.execute(StandardServer.java:1701)
        at com.goldencode.p2j.main.StandardServer.invoke(StandardServer.java:1201)
        at com.goldencode.p2j.main.StandardServer.standardEntry(StandardServer.java:364)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.goldencode.p2j.util.MethodInvoker.invoke(MethodInvoker.java:76)
        at com.goldencode.p2j.net.Dispatcher.processInbound(Dispatcher.java:693)
        at com.goldencode.p2j.net.Conversation.block(Conversation.java:319)
        at com.goldencode.p2j.net.Conversation.run(Conversation.java:163)
        at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.RuntimeException: Non-indexed method getHours is expected for the DMO type com.goldencode.testcases.dmo.p2j_test.Person.
        at com.goldencode.p2j.persist.FieldReference.fetchIndexedPropertyMethods(FieldReference.java:1946)
        at com.goldencode.p2j.persist.FieldReference.getGetter(FieldReference.java:483)
        at com.goldencode.p2j.persist.FieldReference.<init>(FieldReference.java:255)
        at com.goldencode.p2j.persist.DMOSorter$FieldWorker.<init>(DMOSorter.java:151)
        at com.goldencode.p2j.persist.DMOSorter.<init>(DMOSorter.java:63)
        at com.goldencode.p2j.persist.IndexHelper.lookupIndexForSort(IndexHelper.java:841)
        at com.goldencode.p2j.persist.IndexHelper.getIndexForSort(IndexHelper.java:233)
        at com.goldencode.p2j.persist.RandomAccessQuery.<init>(RandomAccessQuery.java:984)
        at com.goldencode.p2j.persist.RandomAccessQuery.<init>(RandomAccessQuery.java:921)
        at com.goldencode.p2j.persist.FindQuery.<init>(FindQuery.java:357)
        at com.goldencode.p2j.persist.FindQuery.<init>(FindQuery.java:248)
        at com.goldencode.p2j.persist.dynquery.InMemP2jQuery1.execute(InMemP2jQuery1.java:18)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.goldencode.p2j.persist.DynamicQueryHelper.compileQuery(DynamicQueryHelper.java:872)
        at com.goldencode.p2j.persist.DynamicQueryHelper.parse(DynamicQueryHelper.java:288)
        at com.goldencode.p2j.persist.DynamicQueryHelper.parseFindQuery(DynamicQueryHelper.java:475)
        at com.goldencode.p2j.persist.BufferImpl._find(BufferImpl.java:2861)
        at com.goldencode.p2j.persist.BufferImpl.findFirst(BufferImpl.java:1812)
        at com.goldencode.testcases.Test$1.body(Test.java:41)
        at com.goldencode.p2j.util.BlockManager.processBody(BlockManager.java:7048)
        at com.goldencode.p2j.util.BlockManager.topLevelBlock(BlockManager.java:6881)
        at com.goldencode.p2j.util.BlockManager.externalProcedure(BlockManager.java:221)
        at com.goldencode.p2j.util.BlockManager.externalProcedure(BlockManager.java:203)
        at com.goldencode.testcases.Test.execute(Test.java:28)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.goldencode.p2j.util.Utils.invoke(Utils.java:1238)
        at com.goldencode.p2j.main.StandardServer$MainInvoker.execute(StandardServer.java:1701)
        at com.goldencode.p2j.main.StandardServer.invoke(StandardServer.java:1201)
        at com.goldencode.p2j.main.StandardServer.standardEntry(StandardServer.java:364)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.goldencode.p2j.util.MethodInvoker.invoke(MethodInvoker.java:76)
        at com.goldencode.p2j.net.Dispatcher.processInbound(Dispatcher.java:693)
        at com.goldencode.p2j.net.Conversation.block(Conversation.java:319)
        at com.goldencode.p2j.net.Conversation.run(Conversation.java:163)
        at java.lang.Thread.run(Thread.java:744)

#3 Updated by Eric Faulhaber over 9 years ago

Thanks, Vadim. So, this tells us that we do not get a runtime error in Progress when invoking BUFFER-VALUE on an extent field. It just returns unknown value. Have you tried something like the following?

def buffer b for person.
def var hrs as int extent 5.
def var hBuffer as handle.
hBuffer = buffer b:handle.

hBuffer:FIND-FIRST.
hrs = hBuffer:BUFFER-FIELD("hours"):BUFFER-VALUE().
MESSAGE hrs[1].

Also, BUFFER-VALUE() is writable, so we should be able to put it on the left side of an assignment expression. Would you please try a test where we try to bulk assign a prepopulated int variable of extent 5 to it (i.e., hBuffer:BUFFER-FIELD("hours"):BUFFER-VALUE() = hrs), and then see if we can access an individual element from the person.hours field?

Once you have checked your test cases into the testcases project, please post their names here.

#4 Updated by Vadim Nebogatov over 9 years ago

Test testcases/uast/denormalization/bulk2:

def bufer b for person.
def var hrs as int extent 5.
def var hBuffer as handle.
hBuffer = buffer b:handle.

hBuffer:FIND-FIRST.
hrs = hBuffer:BUFFER-FIELD("hours"):BUFFER-VALUE().
MESSAGE hrs[1].

Progress output:

0

Converted code with the same schema hints like in note 2 fails with the same fetchIndexedPropertyMethods exception like in note 2.

#5 Updated by Vadim Nebogatov over 9 years ago

Test testcases/uast/denormalization/bulk3:

def buffer b for person.
def var hBuffer as handle.
hBuffer = buffer b:handle.

def var hrs as int extent 5 initial [0, 1, 2, 3, 4].

hBuffer:FIND-FIRST.
DO TRANSACTION ON ERROR UNDO, RETURN NO-APPLY:

hBuffer:BUFFER-FIELD("hours"):BUFFER-VALUE() = hrs.

END.

MESSAGE hBuffer:BUFFER-FIELD("hours"):BUFFER-VALUE(1).
MESSAGE hBuffer:BUFFER-FIELD("hours"):BUFFER-VALUE(2).
MESSAGE hBuffer:BUFFER-FIELD("hours"):BUFFER-VALUE(3).
MESSAGE hBuffer:BUFFER-FIELD("hours"):BUFFER-VALUE(4).

Progress output:

0
1
2
3

Converted code with the same schema hints like in note 2 fails with the same fetchIndexedPropertyMethods exception like in note 2 (happens on FIND-FIRST).

#6 Updated by Vadim Nebogatov over 9 years ago

Test cases are checked in to testcases/uast/denormalization folder.

#7 Updated by Eric Faulhaber about 8 years ago

  • Status changed from New to Test

I believe this issue was addressed with P2J trunk rev 10977.

Also available in: Atom PDF