Icon View Thread

The following is the text of the current message along with any replies.
Messages 21 to 30 of 33 total
Thread Using objects in custom functions
Mon, Aug 8 2011 12:08 PMPermanent Link

John Hay

Daniel

What data type is used in functions.createfunction ?

John

Tue, Aug 9 2011 9:11 AMPermanent Link

Daniel W Humphress

Surpass Software LLC

John, the data type is BLOB.

Danny
Tue, Aug 9 2011 9:18 AMPermanent Link

Daniel W Humphress

Surpass Software LLC

John,

Even something as simple as passing a blob to a custom function and returning the same blob will quickly create the error if the blobs returned are fairly large (maybe 400 characters or more).


procedure TCustomSQLFunctions.DBISAMEngineCustomFunction(Sender: TObject;
 const FunctionName: String; FunctionParams: TDBISAMParams;
 var Result: Variant);
var
 BigBlob: string;
begin

 if (AnsiCompareText(FunctionName,'TestFunction')=0) then begin
   BigBlob := FunctionParams[0].AsString;
   Result := BigBlob;
 end;

end;

SQL:

SELECT TestFunction(BigBlobField) FROM TableWithBigBlob
Tue, Aug 9 2011 4:18 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Danny,

<< Even something as simple as passing a blob to a custom function and
returning the same blob will quickly create the error if the blobs returned
are fairly large (maybe 400 characters or more). >>

Can you send me a table that is causing this issue with the simple custom
function ?  I used your code with a table I had here with BLOBs around 32k a
piece, and I cannot get any errors to occur with FastMM4 in full debug mode,
range-checking turned on, etc.

--
Tim Young
Elevate Software
www.elevatesoft.com
Tue, Aug 9 2011 4:19 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

John,

<<  I would suspect it is this call (freeing the variant) causing the
problem and to trace it will require an example custom function which causes
the error. >>

There is no place in the code where I'm freeing a variant.  Any time there
is a non-ordinal type returned from the custom function, the contents of the
variant are move'd to another buffer that is allocated for that purpose (and
freed later).

--
Tim Young
Elevate Software
www.elevatesoft.com
Wed, Aug 10 2011 6:01 AMPermanent Link

John Hay


Tim
>
> There is no place in the code where I'm freeing a variant.  Any time there
> is a non-ordinal type returned from the custom function, the contents of the
> variant are move'd to another buffer that is allocated for that purpose (and
> freed later).
>

You are right.  More accurately I should have said  the buffer which is used for the return value allocated in
customfunctioncallback.

I then asked about the datatype because looking in customfunctioncallback if the return type was a string and the
function returned a string greater than max_field_size this looks like it will cause a memory overwrite.

John

Wed, Aug 10 2011 12:50 PMPermanent Link

Daniel W Humphress

Surpass Software LLC

John & Tim,

I have spent the day whittling this down into a simple test program to reproduce the problem.

Oddly, just returning a static string or, as I earlier suggested, returning back the string passed to the function doesn't cause the problem. The problem happens when certain string copy and concatenation operations happen within a function and on large strings.

I have created a test program with a rather convoluted looking user function that always returns the same string after doing some manipulation on it (this is basically what my function does but it's much more complex obviously).

The project and database are in the attached zip. The table doesn't really matter. I just use "SELECT Test('xxx') FROM InvCtrl" and Test() always returns the same thing that has nothing to do with the table. I'm sending a sample table just in case!

I am using Delphi 2007 and DBISAM 4.27 Build 5. I have stayed there for now because we have 1000s of users with combinations of different apps accessing a shared database and I don't want to risk having them run an old application against a 4.28+ database and corrupt it. I'm willing to deal with that, though, if we can get this fixed.

What happens for me is that it gets through 2 records then locks up in the function where it's copying and concatenating strings.

Thanks,
Danny



Attachments: DBISAMTest.zip
Wed, Aug 10 2011 1:24 PMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Daniel


Just a small point of etiquette - please do not post large attachments into the normal newsgroups - use the binaries.

Roy Lambert
Wed, Aug 10 2011 1:42 PMPermanent Link

Daniel W Humphress

Surpass Software LLC

Roy Lambert wrote:

Just a small point of etiquette - please do not post large attachments into the normal newsgroups - use the binaries.


Oh, I'm sorry! I didn't realize. Thanks for pointing that out to me, Roy.
Wed, Aug 10 2011 3:08 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Danny,

Just make this change in your code:

constructor TTestSQLFunctions.Create( AEngine: TDBISAMEngine );
begin
 inherited Create;
 FEngine := AEngine;
 FServerVersion := '';
 with AEngine do begin
   with Functions.CreateFunction(ftMemo,'Test').Params do begin  <<<< Here
use ftMemo, not ftString
     CreateFunctionParam(ftString);
   end;
   OnCustomFunction := DBISAMEngineCustomFunction;
 end;
end;

The function parameters in the TDBISAMEngine mirror those of the field
definitions, meaning that anything with a MAX_FIELD_SIZE or less can be an
ftString, but if you think you're going to need to pass in something larger,
you should use ftMemo instead.

Having said that, I'll at least make sure to fix the problem so that it
doesn't cause an AV.

--
Tim Young
Elevate Software
www.elevatesoft.com
« Previous PagePage 3 of 4Next Page »
Jump to Page:  1 2 3 4
Image