How do I construct a varlena?

Started by Oliver Elphickover 27 years ago5 messages
#1Oliver Elphick
olly@lfix.co.uk

Can you tell me, please, how to construct a varlena (to be returned by
a function).

I see it is declared as an int and a 1-byte array; I don't know how to
assign a longer string in place of that 1-byte array; the compiler
complains about incompatible types, whatever I do.

Thank you.

--
Oliver Elphick Oliver.Elphick@lfix.co.uk
Isle of Wight http://www.lfix.co.uk/oliver
PGP key from public servers; key ID 32B8FAA1
========================================
"And not only so, but we glory in tribulations also;
knowing that tribulation worketh patience; And
patience, experience; and experience, hope."
Romans 5:3,4

#2Maarten Boekhold
maartenb@dutepp2.et.tudelft.nl
In reply to: Oliver Elphick (#1)
Re: [HACKERS] How do I construct a varlena?

On Tue, 4 Aug 1998, Oliver Elphick wrote:

Can you tell me, please, how to construct a varlena (to be returned by
a function).

I see it is declared as an int and a 1-byte array; I don't know how to
assign a longer string in place of that 1-byte array; the compiler
complains about incompatible types, whatever I do.

If I'm correct:

malloc(sizeof(VARLENA) + l);

where 'l' is the length of the string you want to put in (without the
trailing '\0').

Maarten

_____________________________________________________________________________
| TU Delft, The Netherlands, Faculty of Information Technology and Systems |
| Department of Electrical Engineering |
| Computer Architecture and Digital Technique section |
| M.Boekhold@et.tudelft.nl |
-----------------------------------------------------------------------------

#3Oliver Elphick
olly@lfix.co.uk
In reply to: Maarten Boekhold (#2)
Re: [HACKERS] How do I construct a varlena?

Maarten Boekhold wrote:

On Tue, 4 Aug 1998, Oliver Elphick wrote:

Can you tell me, please, how to construct a varlena (to be returned by
a function).

I see it is declared as an int and a 1-byte array; I don't know how to
assign a longer string in place of that 1-byte array; the compiler
complains about incompatible types, whatever I do.

If I'm correct:

malloc(sizeof(VARLENA) + l);

where 'l' is the length of the string you want to put in (without the
trailing '\0').

Thanks for your reply; I've been away a few days so I've only just seen it.

My problem is in how to get the compiler to treat the malloced space as
a varlena.

I have this (abridged) C code, to be used with
CREATE FUNCTION cname(bpchar, bpchar, bpchar) returns bpchar ...:

char *cxname;

text cname (text s, text t, text f)
{
text *result;
...
cxname = realloc((void *) cxname, strlen(tmp)+sizeof(struct varlena));
strcpy(cxname+sizeof(int32), tmp);
-> result = &((struct varlena) cxname);
result->vl_len = strlen(tmp);

return *result;
}

but the compiler gives the error `conversion to non-scalar type requested'
at the marked line.

Once I know how to do this, I will add it to the examples in the CREATE
FUNCTION documentation, since it will no doubt be helpful to others.

--
Oliver Elphick Oliver.Elphick@lfix.co.uk
Isle of Wight http://www.lfix.co.uk/oliver
PGP key from public servers; key ID 32B8FAA1
========================================
"...ask, and ye shall receive, that your joy may be
full." John 16:24

#4Thomas G. Lockhart
lockhart@alumni.caltech.edu
In reply to: Oliver Elphick (#3)
Re: [HACKERS] How do I construct a varlena?

My problem is in how to get the compiler to treat the malloced space
as a varlena.
I have this (abridged) C code, to be used with
CREATE FUNCTION cname(bpchar, bpchar, bpchar) returns bpchar ...:

char *cxname;

text cname (text s, text t, text f)

text *cname (text s, text t, text f)

{
text *result;
...
cxname = realloc((void *) cxname,
strlen(tmp)+sizeof(struct varlena));

strcpy is dangerous because it will copy the trailing null, while text
and other varlena types are not guaranteed to be null-terminated. Better
to use memmove() or strncpy().

strcpy(cxname+sizeof(int32), tmp);

strcpy(cxname+sizeof(result->vl_len), tmp);
or
strcpy(cxname+sizeof(VARHDRSZ), tmp);
not sure where tmp came from...

-> result = &((struct varlena) cxname);

cxname is already a pointer. And why not make it a pointer to text
instead of a pointer to char?
result = ((text *) cxname);

result->vl_len = strlen(tmp);

return *result;
}
Once I know how to do this, I will add it to the examples in the
CREATE FUNCTION documentation, since it will no doubt be helpful to
others.

There is already documentation on this (though it could stand to be
cleaned up and augmented) in doc/src/sgml/xfunc.sgml. This appears in
the Programmer's Guide in the chapter titled "Extending SQL: Functions".

If you want, it's probably OK to keep the SQL reference docs pretty
simple, and if there is an example of C source code it could be shown
but then described more completely in the Programmer's Guide. Or we
could just mention that there _are_ examples in the Programmer's Guide
and leave it at that.

There is some code following which gives a (simpler) example...

- Tom

From the varlena.c file in backend/utils/adt/:

/*
* textin - converts "..." to internal representation
*/
text *
textin(char *inputText)
{
text *result;
int len;

if (inputText == NULL)
return (NULL);

len = strlen(inputText) + VARHDRSZ;
result = (text *) palloc(len);
VARSIZE(result) = len;

memmove(VARDATA(result), inputText, len - VARHDRSZ);

#ifdef CYR_RECODE
convertstr(VARDATA(result), len - VARHDRSZ, 0);
#endif

return (result);
}

#5Maarten Boekhold
maartenb@dutepp2.et.tudelft.nl
In reply to: Oliver Elphick (#3)
Re: [HACKERS] How do I construct a varlena?

My problem is in how to get the compiler to treat the malloced space as
a varlena.

I have this (abridged) C code, to be used with
CREATE FUNCTION cname(bpchar, bpchar, bpchar) returns bpchar ...:

char *cxname;

text cname (text s, text t, text f)
{
text *result;
...
cxname = realloc((void *) cxname, strlen(tmp)+sizeof(struct varlena));
strcpy(cxname+sizeof(int32), tmp);
-> result = &((struct varlena) cxname);
result->vl_len = strlen(tmp);

return *result;
}

but the compiler gives the error `conversion to non-scalar type requested'
at the marked line.

I gues something like this should work:

struct varlena *cxname

cxname = (struct varlena *)
realloc(cxname, strlen(tmp) + VARHDRSZ);
strcpy(cxname->vl_dat, tmp); /* maybe '&cxname->vl_dat' */
return cxname;

I don't think it's possible to 'return *cxname', cos the compiler will
only return the part of your data.

Most of this is from head, so check on things if they don't work immediately.

Maarten

_____________________________________________________________________________
| TU Delft, The Netherlands, Faculty of Information Technology and Systems |
| Department of Electrical Engineering |
| Computer Architecture and Digital Technique section |
| M.Boekhold@et.tudelft.nl |
-----------------------------------------------------------------------------