Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
Home -> Community -> Usenet -> c.d.o.misc -> custom aggregate function in C++
I'm using Oracle 9i.
While writing aggregate function which is supposed to find the smallest
distance between points in 3d space I faced a problem which can be
considered serious as far as an Oracle newbie like me is concerned.
My function executes but it crashes just after the ODCIAggregateInitialize
function. I repeatedly get the same error, which is
ORA-00600: internal error code, arguments: [17099], [], [], [], [], [], [], [] ORA-28576: RPC agent connection lost
I know that ODCIAggregateIterate never happens to run. This is my PL/SQL type definition:
TYPE MINDISTANCEIMPL as object (
counter number,
static function ODCIAggregateInitialize(sctx IN OUT MinDistanceImpl)
return number as language C
library distance name "ODCIAggregateInitialize"
with context
parameters (
context,
sctx,
sctx INDICATOR STRUCT,
RETURN INDICATOR ),
member function ODCIAggregateIterate(
self IN OUT MinDistanceImpl,
value IN Coordinates)
return number as language C
library distance name "ODCIAggregateIterate"
with context
parameters (
context,
self,
self INDICATOR STRUCT,
value,
value INDICATOR STRUCT,
RETURN INDICATOR ),
member function ODCIAggregateTerminate(
self IN MinDistanceImpl, returnValue OUT number,
flags IN number) return number as language C
library distance name "ODCIAggregateTerminate"
with context
parameters (
context,
self,
self INDICATOR STRUCT,
returnValue ,
returnValue INDICATOR,
flags,
flags INDICATOR ,
RETURN INDICATOR), member function ODCIAggregateMerge(
self IN OUT MinDistanceImpl,
ctx2 IN MinDistanceImpl)
return number
);
Here is my C++ implementation (written in DLL)
// distancedll.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include <odci.h>
#include <oci.h>
#include <stdio.h>
#include <ociextp.h>
#include <math.h>
#include <fstream>
struct MinDistanceImpl
{
OCINumber* COUNTER;
};
struct MinDistanceImpl_ind
{
OCIInd _atomic;
OCIInd COUNTER;
};
struct DoubleCoordinates{
double x;
double y;
double z;
};
struct Coordinates
{
OCINumber X;
OCINumber Y;
OCINumber Z;
Coordinates(OCINumber xx, OCINumber yy, OCINumber zz): X(xx), Y(yy), Z(zz) {}
};
struct Coordinates_ind
{
OCIInd _atomic;
OCIInd X;
OCIInd Y;
OCIInd Z;
};
extern "C"
{
double dist(DoubleCoordinates c1, DoubleCoordinates c2);
double sq(double x);
DoubleCoordinates convert(Coordinates c,OCIError *errh);
static vector<Coordinates> vect;
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
__declspec(dllexport) int ODCIAggregateInitialize(
OCIExtProcContext *context,
MinDistanceImpl * sctx,
MinDistanceImpl_ind * sctx_ind)
{
ofstream out("c:\\orainit.txt", ios_base::app);
out << "just initialized\n";
vect.clear();
out<< "cleared vector\n";
out.close();
return ODCI_SUCCESS;
}
/*
(
context,
self,
self INDICATOR STRUCT,
value,
value INDICATOR STRUCT,
RETURN INDICATOR ),
*/
__declspec(dllexport) int ODCIAggregateIterate(
OCIExtProcContext *context,
MinDistanceImpl * self,
MinDistanceImpl_ind * self_ind,
Coordinates value,
Coordinates_ind value_ind)
{
ofstream out("c:\\oraiterate.txt", ios_base::app);
out << "\n\n=================\nJust initialized\n";
vect.push_back(value);
out<<"pushed value\n";
out.close();
return ODCI_SUCCESS;
}
__declspec(dllexport) int ODCIAggregateTerminate(
OCIExtProcContext *context,
MinDistanceImpl * self,
MinDistanceImpl_ind * self_ind,
OCINumber * returnValue,
short returnValue_ind,
OCINumber * flags,
short flags_ind)
{
OCIError *errh;
OCIEnv * envh;
OCISvcCtx * svcc;
sword err;
sword status;
ofstream out("c:\\oraterminate.txt", ios_base::app);
out << "just initialized\n";
err = OCIExtProcGetEnv(context, &envh, &svcc, &errh);
out << "set up context\n";
//if(!vect.size())
// return ODCI_ERROR;
double d=0.0;
double minValue = -1.0;
int marker = 0;
for(unsigned int i=0;i<vect.size();i++)
{
out << "new big loop:" << i<<"\n";
for(unsigned int j=i;j<vect.size();j++)
{
out << "in small loop: "<<j<<"\n";
d = dist(convert(vect[i],errh), convert(vect[j],errh));
out << "just computed distance\n";
if(minValue==-1.0 || d<minValue)
{
out << "new minValue chosen\n";
minValue = d;
}
}
}
out << "after loops\n";
if(returnValue==NULL)
{
out << "return value is null\n";
returnValue = (OCINumber*) OCIExtProcAllocCallMemory(context, sizeof(OCINumber));
}
out << "before conversion of returnValue\n";
status = OCINumberFromReal(errh, &minValue, sizeof(minValue), returnValue);
out << "after conversion of returnValue\n";
out.close();
return ODCI_SUCCESS;
}
DoubleCoordinates convert(Coordinates c,OCIError *errh)
{
sword status;
double x = 0.0;
double y = 0.0;
double z = 0.0;
status = OCINumberToInt ( errh,&c.X,sizeof(double),OCI_NUMBER_SIGNED, &x );
status = OCINumberToInt ( errh,&c.Y,sizeof(double),OCI_NUMBER_SIGNED, &y );
status = OCINumberToInt ( errh,&c.Z,sizeof(double),OCI_NUMBER_SIGNED, &z );
DoubleCoordinates * dc = (DoubleCoordinates *)malloc(sizeof(DoubleCoordinates));
dc->x = x;
dc->y = y;
dc->z = z;
return *(dc);
}
double dist(DoubleCoordinates c1, DoubleCoordinates c2)
{
return sqrt((c1.x-c2.x)+sq(c1.y-c2.y)+sq(c1.z-c2.z));
}
double sq(double x)
{
return x*x;
}
} // of extern "c"
I've added these file output lines for debugging, It does not work without them either.
And at last I include the database table declaration together with code creating the aggregate function and a try to run it:
function MinDistance(val in Coordinates)
return number
aggregate using MinDistanceImpl;
create or replace type Coordinates as object (
x number,
y number,
z number
);
SELECT MinDistance(point) FROM POINTS3D;
The Points3D table is nonemty.
Can anyone help me find the bug, because I'm totally lost :(
Marcin Moczyróg Received on Fri Nov 11 2005 - 14:30:27 CST