[GENERAL] Problem with Numerics multiplication in C-function

2009-08-02 Thread Ilya Urikh
Hi, I have a strange problem with Numeric multiplication in C-function.

There are 2 functions getRate and getVAT which return Numeric. In 3rd
function calculateService I try to multiply the results of getRate and
getVAT. After execution I have two types of error, some time without
messages and with message "Invalid memory alloc ... ".
If I initialize the Numeric variables inside calculateService and multiply,
function numeric_mul works fine.

PostgreSQL 8.3.7

Datum getRate(PG_FUNCTION_ARGS) {
int32 accountId = PG_GETARG_INT32(0);
int16 serviceId = PG_GETARG_INT16(1);
DateADT date = PG_GETARG_DATEADT(2);

bool isNull;
char command[QUERY_MAX_SIZE];
char message[MESSAGE_MAX_SIZE];

Numeric rate = DatumGetNumeric(DirectFunctionCall3(numeric_in,
CStringGetDatum(RATE_ERROR_CSTRING_VALUE), 0, -1));

//Build SQL query
snprintf(command, sizeof (command), "...");

SPI_connect();
SPI_execute(command, true, 0);
rate = DatumGetNumeric(SPI_getbinval(SPI_tuptable->vals[0],
 SPI_tuptable->tupdesc,
 1,
 &isNull));

#ifdef PR_DEBUG
snprintf(message, sizeof (message), " getRate: Returns rate =
%s.",
DatumGetCString(DirectFunctionCall1(numeric_out,
NumericGetDatum(rate;
elog(INFO, message);
#endif
SPI_finish();
PG_RETURN_NUMERIC(rate);
}

Datum calculateService(PG_FUNCTION_ARGS) {
// Like the getRate
}

Datum calculateService(PG_FUNCTION_ARGS) {
int32   accountId = PG_GETARG_INT32(0);
int16   serviceId = PG_GETARG_INT16(1);
DateADT date = PG_GETARG_DATEADT(2);
int32   transactionRegisterId = PG_GETARG_INT32(3);

Numeric rate;
Numeric vat;
Numeric amount;

rate = DatumGetNumeric(DirectFunctionCall3(getRate,
Int32GetDatum(accountId),
Int16GetDatum(serviceId),
DateADTGetDatum(date)));
vat = DatumGetNumeric(DirectFunctionCall1(getVAT,
DateADTGetDatum(date)));

#ifdef PR_DEBUG
snprintf(message, sizeof (message), " calculateService: rate =
%s, vat",
DatumGetCString(DirectFunctionCall1(numeric_out,
NumericGetDatum(rate;
elog(INFO, message);
#endif

amount = DatumGetNumeric(DirectFunctionCall2(numeric_mul,
NumericGetDatum(rate),
NumericGetDatum(vat)));

    // ERROR
...
}


-- 
Best regards,
Ilya Urikh.


[GENERAL] Problem with Numerics multiplication in C-function

2009-08-02 Thread Ilya Urikh
Hi, I have a strange problem with Numeric multiplication in C-function.

There are 2 functions getRate and getVAT which return Numeric. In 3rd
function calculateService I try to multiply the results of getRate and
getVAT. After execution I have two types of error, some time without
messages and with message "Invalid memory alloc ... ".
If I initialize the Numeric variables inside calculateService and
multiply, function numeric_mul works fine.

PostgreSQL 8.3.7

Datum getRate(PG_FUNCTION_ARGS) {
int32 accountId = PG_GETARG_INT32(0);
int16 serviceId = PG_GETARG_INT16(1);
DateADT date = PG_GETARG_DATEADT(2);

bool isNull;
char command[QUERY_MAX_SIZE];
char message[MESSAGE_MAX_SIZE];

Numeric rate = DatumGetNumeric(DirectFunctionCall3(numeric_in,
CStringGetDatum(RATE_ERROR_CSTRING_VALUE), 0, -1));

//Build SQL query
snprintf(command, sizeof (command), "...");

SPI_connect();
SPI_execute(command, true, 0);
rate = DatumGetNumeric(SPI_getbinval(SPI_tuptable->vals[0],
 SPI_tuptable->tupdesc,
 1,
 &isNull));

#ifdef PR_DEBUG
snprintf(message, sizeof (message), " getRate: Returns rate =
%s.",
DatumGetCString(DirectFunctionCall1(numeric_out,
NumericGetDatum(rate;
elog(INFO, message);
#endif
SPI_finish();
PG_RETURN_NUMERIC(rate);
}

Datum calculateService(PG_FUNCTION_ARGS) {
// Like the getRate
}

Datum calculateService(PG_FUNCTION_ARGS) {
int32   accountId = PG_GETARG_INT32(0);
int16   serviceId = PG_GETARG_INT16(1);
DateADT date = PG_GETARG_DATEADT(2);
int32   transactionRegisterId = PG_GETARG_INT32(3);

Numeric rate;
Numeric vat;
Numeric amount;

rate = DatumGetNumeric(DirectFunctionCall3(getRate,
Int32GetDatum(accountId),
Int16GetDatum(serviceId),
DateADTGetDatum(date)));
vat = DatumGetNumeric(DirectFunctionCall1(getVAT,
DateADTGetDatum(date)));

#ifdef PR_DEBUG
snprintf(message, sizeof (message), " calculateService: rate
= %s, vat",
DatumGetCString(DirectFunctionCall1(numeric_out,
NumericGetDatum(rate;
elog(INFO, message);
#endif

amount = DatumGetNumeric(DirectFunctionCall2(numeric_mul,
NumericGetDatum(rate),
NumericGetDatum(vat)));

// ERROR
...
}


Best regards,
Ilya Urikh.



Re: [GENERAL] Problem with Numerics multiplication in C-function

2009-08-03 Thread Ilya Urikh
Thank's a lot! That's really help. I failed to bear memory context switching
in mind.
I resolved this problem with following strings in *getRate*:

  result = SPI_palloc(sizeof(rate));
  memcpy(result, rate, sizeof(rate));


P.S. I think it's a good idea to add example to documentation. Anyway when I
had started to work with PostgreSQL I was very surprised at so clear and
structured documentation. :)


On Tue, Aug 4, 2009 at 1:44 AM, Martijn van Oosterhout wrote:

> On Mon, Aug 03, 2009 at 10:20:36AM -0400, Tom Lane wrote:
> > Martijn van Oosterhout  writes:
> > > What you need to do is copy the Datum you wish to return into the upper
> > > memory context. I'm not seeing a helpful SPI utility function or
> > > obvious example here you help you, but I'm sure it's something with
> > > MemoryContextSwitchTo() and datumCopy().
> >
> > SPI_palloc is what to use to allocate the result in the right place.
>
> Ofcourse, and then a memcpy(). I was distracted by the fact there is an
> SPI_copy/returntuple(), but no SPI_returndatum(). It might actually be
> helpful to include in the documentation an example of returning from a
> function a result from SPI, since it's not entirely obvious.
>
> Have a nice day,
> --
> Martijn van Oosterhout  http://svana.org/kleptog/
> > Please line up in a tree and maintain the heap invariant while
> > boarding. Thank you for flying nlogn airlines.
>
> -BEGIN PGP SIGNATURE-
> Version: GnuPG v1.4.9 (GNU/Linux)
>
> iD8DBQFKdvezIB7bNG8LQkwRAiwGAJ0dyrP+JROL9F/OhKvzLlR5O2h4tACdEIAE
> QvCDFfLfnzCpkti8PXcVp38=
> =ZXiG
> -END PGP SIGNATURE-
>
>


-- 
Best regards,
Ilya Urikh.


[GENERAL] Problem with using snprintf in C-function

2009-10-17 Thread Ilya Urikh
Hi,

I have a problem with snprintf function which insert the variables to string
with error.
This code I wrote for PostgreSQL 8.3.7 on Fedora 10 and it worked fine. But
now I use CentOS 5.3 and PostgreSQL 8.3.8.

Function:
Datum calculateAccount(PG_FUNCTION_ARGS) {
int64   accountId = PG_GETARG_INT64(0);
DateADT startDate = PG_GETARG_DATEADT(1);
DateADT endDate = PG_GETARG_DATEADT(2);

charcommand[QUERY_MAX_SIZE];
charstartDateStr[MAXDATELEN + 3];
charendDateStr[MAXDATELEN + 3];

snprintf(startDateStr, sizeof (startDateStr), "'%s'",
DatumGetCString(DirectFunctionCall1(date_out, startDate)));
snprintf(endDateStr, sizeof (endDateStr), "'%s'",
DatumGetCString(DirectFunctionCall1(date_out, endDate)));
elog(INFO, startDateStr);
elog(INFO, endDateStr);
snprintf(command, sizeof (command),
"SELECT serviceId, periodStartDate, periodEndDate\
 FROM   accountServiceBaseView\
 WHERE  accountId = %ld AND\
periodStartDate <= %s AND\
periodEndDate >= %s;",
accountId, startDateStr, endDateStr);
elog(INFO, command);

PG_RETURN_BOOL(true);
}

Result:
select calculateaccount(123, '01-01-2009', '01-02-2009');
INFO:  '2009-01-01'
INFO:  '2009-02-01'
INFO:  SELECT serviceId, periodStartDate, periodEndDate FROM
accountServiceBaseView WHERE  accountId = 123 AND periodStartDate <= (null)
AND periodEndDate >= '2009-01-01';


If I change the order of parameters to "periodStartDate <= %s AND
periodEndDate >= %s AND accountId = %ld", all works fine. Unfortunately this
method can not be applied to other functions of my module.


-- 
Best regards,
Ilya Urikh.


Re: [GENERAL] Problem with using snprintf in C-function

2009-10-17 Thread Ilya Urikh
Pavel,

Could you provide some example? I don't really understand which placeholder
I can use.


On Sun, Oct 18, 2009 at 1:20 AM, Pavel Stehule wrote:

> 2009/10/17 Ilya Urikh :
> > Hi,
> >
> > I have a problem with snprintf function which insert the variables to
> string
> > with error.
> > This code I wrote for PostgreSQL 8.3.7 on Fedora 10 and it worked fine.
> But
> > now I use CentOS 5.3 and PostgreSQL 8.3.8.
> >
> > Function:
> > Datum calculateAccount(PG_FUNCTION_ARGS) {
> > int64   accountId = PG_GETARG_INT64(0);
> > DateADT startDate = PG_GETARG_DATEADT(1);
> > DateADT endDate = PG_GETARG_DATEADT(2);
> >
> > charcommand[QUERY_MAX_SIZE];
> > charstartDateStr[MAXDATELEN + 3];
> > charendDateStr[MAXDATELEN + 3];
> >
> > snprintf(startDateStr, sizeof (startDateStr), "'%s'",
> > DatumGetCString(DirectFunctionCall1(date_out, startDate)));
> > snprintf(endDateStr, sizeof (endDateStr), "'%s'",
> > DatumGetCString(DirectFunctionCall1(date_out, endDate)));
> > elog(INFO, startDateStr);
> > elog(INFO, endDateStr);
> > snprintf(command, sizeof (command),
> > "SELECT serviceId, periodStartDate, periodEndDate\
> >  FROM   accountServiceBaseView\
> >  WHERE  accountId = %ld AND\
> > periodStartDate <= %s AND\
> > periodEndDate >= %s;",
> > accountId, startDateStr, endDateStr);
> > elog(INFO, command);
> >
>
> Hello
>
> my reply is little bit offtopic. Why you convert date values to
> string? You can use placeholders and execute query with parameters in
> native format. It's more simply and safe.
>
> Regards
> Pavel Stehule
>
>
>
>
> > PG_RETURN_BOOL(true);
> > }
> >
> > Result:
> > select calculateaccount(123, '01-01-2009', '01-02-2009');
> > INFO:  '2009-01-01'
> > INFO:  '2009-02-01'
> > INFO:  SELECT serviceId, periodStartDate, periodEndDate FROM
> > accountServiceBaseView WHERE  accountId = 123 AND periodStartDate <=
> (null)
> > AND periodEndDate >= '2009-01-01';
> >
> >
> > If I change the order of parameters to "periodStartDate <= %s AND
> > periodEndDate >= %s AND accountId = %ld", all works fine. Unfortunately
> this
> > method can not be applied to other functions of my module.
> >
> >
> > --
> > Best regards,
> > Ilya Urikh.
> >
>



-- 
Best regards,
Ilya Urikh.