Retrieve data selection variable

Hi. Does anyone have documentation for B4302450, UBE Retrieve Data Selection cache? I can't seem to figure out the parameters.

I was hoping that 9.1 would make it easier to retrieve data selection values.
 
Hi. Please take a look at R4304016 to see how UBERetrieveDataSelectionCache - B4302450 is used.
 
Hi All,

The attachement are now working and here is the Code from Jeremy. Thanks Jeremy.

Christian Audet


Hi Christian,

I found your piece of code and installed it and it works fine.
I tried running it from a test UBE passing in different PID / VERS / SECTIONid and all returned the correct DS.
BUT when I try to call the BSFN from an APPL and passing in the same parameters it goes in error on the call to "ubeSection_GetDataSelection".
It seems that the lpBhvrCom is passing in values that are not accepted somehow.
Do you have a tip for me how to solve this issue?

With kind regards,
Chris.
 
Well Chris, this attachment was posted to JDEList 13 years ago :) I am sure there might be some challenges in today's release. This code was originally posted by Jeremy. Now your question is not detailed enough to attempt any reply. Provide the detail of what you want to do, how you are doing it, possibly showing the code. Then detail of what is working because you state that "It's working fine" and detail of the errors you are getting.
 
Hello Jeremy and Christian. @
I have downloaded it and also implemented it successfully.
When I call the BSFN from a test UBE with random ube names / belonging version / correct section it gives me back the correct data selection of the requested UBE / version.
When I call the BSFN from a test APPL with exactly the same variables the call to "ubeSection_GetDataSelection" returns error.
My guess it has something to do with the "lpBhvrCom" but trying to change all values to the values as called from a UBE doesn't help.
Do you have a suggestion?

With kind regards,
Chris.
 
Hello all,

Yes, it seems people still use this Data Selection business function! However, I am having tons of problems with memory leaks trying to use it. Has anyone who has used this in the last few years run into this and maybe knows why? I had to convert everything to unicode so it may be related. The source code that I used is provided in this thread.

This is the section of code that ends up throwing the memory violation:

Code:
							//------------------------------------------------------------------
							// by default, cast to char...
							//------------------------------------------------------------------
							default:
								pTempValue = (JCHAR *)pVoid + (ii*lBytes);
								jdeStrncpy(szValue, (const JCHAR *)pTempValue, lBytes);
								pTempValue = NULL;
								break;
						}

After a few dozen lines, eventually pTempValue becomes corrupt and the jdeStrncpy function call using a bad pointer throws the error. However, pTempValue is being set to NULL in the variable declaration section and it seems like it should be released from memory. So why is this happening?

Any help greatly appreciated.
 
Try this:

Code:
[COLOR=#333333]pTempValue = (JCHAR *)pVoid + (ii*lBytes/sizeof(JCHAR));[/COLOR]
 
Try this:

Code:
[COLOR=#333333]pTempValue = (JCHAR *)pVoid + (ii*lBytes/sizeof(JCHAR));[/COLOR]

Thanks for the response, Jeremy. And thanks for writing this solution 12 years ago!

I made this change but I'm getting the same problem. I'm debugging in C, and right before it would commit the memory violation and crash, this is the state of that call:

Code:
pTempValue = (JCHAR *)pVoid + (ii*lBytes/sizeof(JCHAR));
//pTempValue = <bad ptr> 0x00000000
//ii == 0
//lBytes == 22
//so... pTempValue = (JCHAR *)pVoid + (0)
jdeStrncpy(szValue, (const JCHAR *)pTempValue, lBytes);
// Will attempt to strncpy a bad pointer; memory violation
 
When you say pTempValue = 0x00000000, is that before or after the assignment: pTempValue = (JCHAR *)pVoid + (ii*lBytes/sizeof(JCHAR));

If after, what is the value of pVoid? And what does that memory look like (if not NULL)?
 
When you say pTempValue = 0x00000000, is that before or after the assignment: pTempValue = (JCHAR *)pVoid + (ii*lBytes/sizeof(JCHAR));

If after, what is the value of pVoid? And what does that memory look like (if not NULL)?

pTempValue = 0x00000000 after the assignment of pTempValue in this case. I assume that the purpose of (ii*lBytes/sizeof(JCHAR)) is to position the pointer for string data. When ii is zero, as it is when there is only one Data Selection value to return, or the first of a series of them, (ii*lBytes/sizeof(JCHAR)) resolves to (0*lBytes/2), or 0. This seems to work until the pointer would address protected space, which throws the memory violation error.

I was trying to figure this out, so I initialized the ii variable to 1 instead of 0 in the for loop. As you might expect, lots of rows are skipped and not printed, but the BSFN doesn't crash and there's no memory violation error. So I really think there's some issue or memory leak associated with the pTempValue assignment.

In trying to fix it, I've changed most of the jdeStrncpy calls to jdeStrncpyTerminate to prevent overwriting, initializing all pointers, and others. Still can't seem to figure this out.
 
If pTempValue is NULL after the assignment, it means pVoid is NULL, which means something is wrong with the determination of that pointer or something is overwriting it between the time it's set and this line you're having trouble with. You didn't answer my question as to what pVoid looks like at the time of that assignment.

It might be easier if you posted your whole function. The purpose of the (ii*lBytes/sizeof(JCHAR)) is to position pTempValue to the correct offset in the list of values. So for the first value in the list, the offset should be 0. pVoid should be pointing to the first value in the list of values... I think that must be invalid at the time of that assignment.
 
If pTempValue is NULL after the assignment, it means pVoid is NULL, which means something is wrong with the determination of that pointer or something is overwriting it between the time it's set and this line you're having trouble with. You didn't answer my question as to what pVoid looks like at the time of that assignment.

It might be easier if you posted your whole function. The purpose of the (ii*lBytes/sizeof(JCHAR)) is to position pTempValue to the correct offset in the list of values. So for the first value in the list, the offset should be 0. pVoid should be pointing to the first value in the list of values... I think that must be invalid at the time of that assignment.
[/COLOR]

pVoid seems to be equal to 0x00000000 at the time of the error.

I have attached my function. Thank you for your help.
 

Attachments

  • B57DS.c.txt
    22.7 KB · Views: 22
  • B57DS.h.txt
    6.4 KB · Views: 10
I think I made a breakthrough on this. How is the SectionID supposed to be populated? Is there a business function or NER that is supposed to return it from the UBE I'm calling this BSFN from? I was passing the sectionID as a System Variable, but it was always '2' because that's the ID of the UBE section I was calling it from. Thus it was returning the SelectStruct with that parameter.

How do you find the Section ID of a UBE and use it in this BSFN?
 
You will generally want to call this from the Initialize Section event of the section that has the data selection. In this case, the SV (SL?) Section ID variable should be the one you want to use.

I think the easiest means of finding/knowing a section's ID is using Patwel's Object Browser utility. If you have that, you can see the ID in parens of each section in the tree view of the report. If you don't have this utility, I highly recommend you get it... you will love it!
 
You will generally want to call this from the Initialize Section event of the section that has the data selection. In this case, the SV (SL?) Section ID variable should be the one you want to use.

I think the easiest means of finding/knowing a section's ID is using Patwel's Object Browser utility. If you have that, you can see the ID in parens of each section in the tree view of the report. If you don't have this utility, I highly recommend you get it... you will love it!

I was wondering about the sectionID variable because my goal is to have this dump the Data Selections for all UBEs on this environment. I built a simple UBE that uses this BSFN and generates for each UBE / Version. Does the SectionID apply to the UBE that calls the BSFN or does it apply to the UBE that it is trying to extract Data Selection data for? It seems like it might be a culprit because it could explain how pVoid keeps become null and crashing the program. Because pVoid is initialized with:

Code:
pVoid = lpSelectStruct[i].lpValue;

and lpSelectStruct is populated by the ubeSection_GetDataSelection API call.

pVoid definitely seems to be the culprit for these memory leaks that crash this BSFN. I fixed the earlier section that kept causing the crash as:

Code:
//------------------------------------------------------------------
// by default, cast to JCHAR...
//------------------------------------------------------------------
default:
 pTempValue = (JCHAR *)pVoid + (ii * lBytes)/sizeof(JCHAR);
 jdeStrncpyTerminate(szValue, (const JCHAR *)pTempValue, DIM(szValue));
 break;

and now it fails on:

Code:
//------------------------------------------------------------------
// if 'Numeric' data type, cast to Math_Numeric and format as string
//------------------------------------------------------------------
 case OW_DATATYPE_NUMERIC:
 lpmnMathNumeric = (LPMATH_NUMERIC)pVoid + ii; 
 FormatMathNumeric(szValue, lpmnMathNumeric); //Fails on this line.
 break;

It fails for the same reason. lpmnMathNumeric is null after the assignment of pVoid + ii, and FormatMathNumeric crashes.

I feel like I keep getting closer. Any ideas?

And yes, I absolutely love Object Browser. I use it for everything.
 
The sectionID would be the ID of the section in the UBE that you want the data selection for.

I was wondering about the sectionID variable because my goal is to have this dump the Data Selections for all UBEs on this environment.

You can do that with the batch export feature in Object Browser. Glad you like it.

Craig
 
I am not sure this API (ubeSection_GetDataSelection) works in such a way as to be able to retrieve DS for non-running UBE|Versions. I think it's meant to work for the currently running UBE.

You can test this functionality by calling your custom UBE and then calling your BSFN with a very specific set of parameters. What I mean by this is look at some UBE (UBE B) for which you want to gather DS info. Find out the driver section ID by looking in Object Browser. Then modify your custom UBE to call your custom function and pass the desired report name (UBE B), the driver section ID of UBE B, and the version of UBE B for which you want DS.

See if that works. I don't know if it does. If it does, then you have another obstacle... you will need to determine at runtime the driver section ID of each UBE for which you will be calling your custom BSFN. That will vary for each UBE. You can't just use the SV Section ID variable of your running UBE and pass that into your function when you are attempting to retrieve DS for another UBE. You must know the driver section ID of the report for which you are calling the BSFN!

Assuming your test works and it does gather DS for any arbitrary UBE, I don't know of a way to programmatically identify the driver section ID for any UBE. It may be stored in the specs. There may be an API available ( I vaguely recall seeing an API function prototype in the past that could be a match for this ). Somebody else with more intimate knowledge of the spec structure may be able to chime in and answer this, but it still depends on that main API working the way in which you are trying to use it. Try that test and see what happens.

There is a commercial tool out there (Everestsoft) that does what you're trying to do. If the API above does not work for non-running UBE's, there is still the option of coding a solution to extract the data selection from the spec files if the commercial tool is not an option.

Good luck.
 
I am not sure this API (ubeSection_GetDataSelection) works in such a way as to be able to retrieve DS for non-running UBE|Versions.

It does (or at least it did last time I checked), on our TR release. I have built solutions in the past that relied on this behavior. I have had some issues in the past when there is NO data selection on a section.
 
JMR said:
See if that works. I don't know if it does. If it does, then you have another obstacle... you will need to determine at runtime the driver section ID of each UBE for which you will be calling your custom BSFN. That will vary for each UBE. You can't just use the SV Section ID variable of your running UBE and pass that into your function when you are attempting to retrieve DS for another UBE. You must know the driver section ID of the report for which you are calling the BSFN!

Yes, this very specific parameter test did work as expected. In my code, I switched passing the sectionID as a Parameter and used the GetID function:

Code:
ubeSection_GetID(lpBhvrCom, &lpDS->mnSectionID);	MathNumericToLong(&lpDS->mnSectionID, (LPLONG) §ionID);

But that only returns the running UBE, as you might expect. Supposedly there is a function called UBEReport_FindDriverSection(), but I haven't found any documentation and I'm not sure how to find out what parameters it needs. It also probably wouldn't return each Section's SectionID to check for data selection. If there was a function that could verify if a Section ID was valid for a given UBE and there was a maximum assignable Section ID number, that could be a solution, but I'm not sure of either of those things.

By any chance Jeremy, did you have a moment to look at my code and the pVoid variable that is crashing this BSFN? At the least, do you have any ideas how lpSelectStruct.lpValue could be equal to null, thus assigning null to pVoid?
 
I eyeballed it and it looks ok. As for how pVoid can be NULL... the only thing that comes to mind is if the bsvw attached to the section is a join view and the current selectstruct is one of the join criteria.

You should probably just ignore the rest of the code if pVoid is NULL after that assignment.
 
Back
Top