creating a new type in C
Hello,
I've been playing with a new type I want to create, but I got stuck,
therefore I ask for your assistance.
I don't know if this is the right list for this, if not please tell me
where to post my questions.
This is the source:
#include "postgres.h"
#include "fmgr.h"
typedef struct movie_property
{
int4 id;
char name[31];
} movie_property;
Datum movie_property_in(PG_FUNCTION_ARGS);
Datum movie_property_out(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(movie_property_in)
Datum movie_property_in(PG_FUNCTION_ARGS)
{
int4 id = PG_GETARG_INT32(0);
char *name = PG_GETARG_CSTRING(1);
movie_property *result;
result = (movie_property *) palloc(sizeof(movie_property));
result->id = id;
strncpy(result->name, name, 30);
result->name[30] = 0;
PG_RETURN_POINTER(result);
}
PG_FUNCTION_INFO_V1(movie_property_out)
Datum movie_property_out(PG_FUNCTION_ARGS)
{
movie_property *property = (movie_property *) PG_GETARG_POINTER(0);
char *result;
if (property == NULL)
PG_RETURN_POINTER(NULL);
if ((result = (char *) palloc(40)) != NULL)
{
sprintf(result, "(%d,%s)", property->id, property->name);
}
PG_RETURN_CSTRING(result);
}
Creating functions and type:
create function movie_property_in(opaque)
returns opaque
as '$libdir/movie_property'
language 'c';
create function movie_property_out(opaque)
returns opaque
as '$libdir/movie_property'
language 'c';
create type movie_property (
internallength = 35,
input = movie_property_in,
output = movie_property_out
);
CREATE TABLE pp (p movie_property);
INSERT INTO pp values('(1, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")');
The problem is with movie_property_in function.
When I try to obtain the id with PG_GETARG_INT32(0),
I don't get 1, but 138944104.
I tried and logged the result of PG_GETARG_CSTRING(0), and it seems it
returns the whole string (1, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").
Please, tell me, how do I do this the right way ?
If you have any other comments regarding my code (I'm a C begginer),
they are welcomed.
Postgresql version is 7.2.3 on a Gentoo Linux 1.2
gcc version 2.95.3 20010315
Hello,
I think you gave the answer for your question by yourself. In the XXX_in
function you have only one args. You have to parse it and covert it into the
proper format by yourself.
The sample code (complex type) very good in the Postgres docs
http://www.postgresql.org/idocs/index.php?xtypes.html
Complex *
complex_in(char *str)
{
double x, y;
Complex *result;
if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2) {
elog(ERROR, "complex_in: error in parsing %s", str);
return NULL;
}
result = (Complex *)palloc(sizeof(Complex));
result->x = x;
result->y = y;
return (result);
}
It uses version 0 calling conversion in the sample, but the rest is the
same.
As you see the sscanf "C" library function is used to convert the argument
string.
In your case it is not going to work, becasue the sscanf in not good enough
to make to conversion. The best way if you write a small function to make it
for you.
Best Regards,
Yuri
----- Original Message -----
From: "Andrei Ivanov" <andrei.ivanov@ines.ro>
To: <pgsql-general@postgresql.org>
Sent: Friday, October 18, 2002 12:29 PM
Subject: [GENERAL] creating a new type in C
Show quoted text
Hello,
I've been playing with a new type I want to create, but I got stuck,
therefore I ask for your assistance.
I don't know if this is the right list for this, if not please tell me
where to post my questions.
This is the source:#include "postgres.h"
#include "fmgr.h"typedef struct movie_property
{
int4 id;
char name[31];
} movie_property;Datum movie_property_in(PG_FUNCTION_ARGS);
Datum movie_property_out(PG_FUNCTION_ARGS);PG_FUNCTION_INFO_V1(movie_property_in)
Datum movie_property_in(PG_FUNCTION_ARGS)
{
int4 id = PG_GETARG_INT32(0);
char *name = PG_GETARG_CSTRING(1);
movie_property *result;
result = (movie_property *) palloc(sizeof(movie_property));
result->id = id;
strncpy(result->name, name, 30);
result->name[30] = 0;
PG_RETURN_POINTER(result);
}PG_FUNCTION_INFO_V1(movie_property_out)
Datum movie_property_out(PG_FUNCTION_ARGS)
{
movie_property *property = (movie_property *) PG_GETARG_POINTER(0);
char *result;if (property == NULL)
PG_RETURN_POINTER(NULL);
if ((result = (char *) palloc(40)) != NULL)
{
sprintf(result, "(%d,%s)", property->id, property->name);
}
PG_RETURN_CSTRING(result);
}Creating functions and type:
create function movie_property_in(opaque)
returns opaque
as '$libdir/movie_property'
language 'c';
create function movie_property_out(opaque)
returns opaque
as '$libdir/movie_property'
language 'c';
create type movie_property (
internallength = 35,
input = movie_property_in,
output = movie_property_out
);
CREATE TABLE pp (p movie_property);
INSERT INTO pp values('(1, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")');The problem is with movie_property_in function.
When I try to obtain the id with PG_GETARG_INT32(0),
I don't get 1, but 138944104.
I tried and logged the result of PG_GETARG_CSTRING(0), and it seems it
returns the whole string (1, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").
Please, tell me, how do I do this the right way ?
If you have any other comments regarding my code (I'm a C begginer),
they are welcomed.Postgresql version is 7.2.3 on a Gentoo Linux 1.2
gcc version 2.95.3 20010315---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?
I see, but aren't all those PG_GETARG_XXX functions supposed to do the
parsing and casting ? I though that's why they existed, to make the
manual parsing unnecessary and maybe eliminate bugs.
And another thought, is this the right query to insert data into this type ?
INSERT INTO pp values('(1, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")');
PS: this is a second reply, because the first time I forgot to CC to the
list, sorry.
On Fri, 18 Oct 2002, Gyorgy Molnar wrote:
Show quoted text
Hello,
I think you gave the answer for your question by yourself. In the XXX_in
function you have only one args. You have to parse it and covert it into the
proper format by yourself.The sample code (complex type) very good in the Postgres docs
http://www.postgresql.org/idocs/index.php?xtypes.htmlComplex *
complex_in(char *str)
{
double x, y;
Complex *result;
if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2) {
elog(ERROR, "complex_in: error in parsing %s", str);
return NULL;
}
result = (Complex *)palloc(sizeof(Complex));
result->x = x;
result->y = y;
return (result);
}It uses version 0 calling conversion in the sample, but the rest is the
same.As you see the sscanf "C" library function is used to convert the argument
string.
In your case it is not going to work, becasue the sscanf in not good enough
to make to conversion. The best way if you write a small function to make it
for you.Best Regards,
Yuri----- Original Message -----
From: "Andrei Ivanov" <andrei.ivanov@ines.ro>
To: <pgsql-general@postgresql.org>
Sent: Friday, October 18, 2002 12:29 PM
Subject: [GENERAL] creating a new type in CHello,
I've been playing with a new type I want to create, but I got stuck,
therefore I ask for your assistance.
I don't know if this is the right list for this, if not please tell me
where to post my questions.
This is the source:#include "postgres.h"
#include "fmgr.h"typedef struct movie_property
{
int4 id;
char name[31];
} movie_property;Datum movie_property_in(PG_FUNCTION_ARGS);
Datum movie_property_out(PG_FUNCTION_ARGS);PG_FUNCTION_INFO_V1(movie_property_in)
Datum movie_property_in(PG_FUNCTION_ARGS)
{
int4 id = PG_GETARG_INT32(0);
char *name = PG_GETARG_CSTRING(1);
movie_property *result;
result = (movie_property *) palloc(sizeof(movie_property));
result->id = id;
strncpy(result->name, name, 30);
result->name[30] = 0;
PG_RETURN_POINTER(result);
}PG_FUNCTION_INFO_V1(movie_property_out)
Datum movie_property_out(PG_FUNCTION_ARGS)
{
movie_property *property = (movie_property *) PG_GETARG_POINTER(0);
char *result;if (property == NULL)
PG_RETURN_POINTER(NULL);
if ((result = (char *) palloc(40)) != NULL)
{
sprintf(result, "(%d,%s)", property->id, property->name);
}
PG_RETURN_CSTRING(result);
}Creating functions and type:
create function movie_property_in(opaque)
returns opaque
as '$libdir/movie_property'
language 'c';
create function movie_property_out(opaque)
returns opaque
as '$libdir/movie_property'
language 'c';
create type movie_property (
internallength = 35,
input = movie_property_in,
output = movie_property_out
);
CREATE TABLE pp (p movie_property);
INSERT INTO pp values('(1, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")');The problem is with movie_property_in function.
When I try to obtain the id with PG_GETARG_INT32(0),
I don't get 1, but 138944104.
I tried and logged the result of PG_GETARG_CSTRING(0), and it seems it
returns the whole string (1, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").
Please, tell me, how do I do this the right way ?
If you have any other comments regarding my code (I'm a C begginer),
they are welcomed.Postgresql version is 7.2.3 on a Gentoo Linux 1.2
gcc version 2.95.3 20010315---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?
Import Notes
Resolved by subject fallback