Thread: How do I construct a varlena?

How do I construct a varlena?

From
"Oliver Elphick"
Date:
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



Re: [HACKERS] How do I construct a varlena?

From
Maarten Boekhold
Date:
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                         |
-----------------------------------------------------------------------------


Re: [HACKERS] How do I construct a varlena?

From
"Oliver Elphick"
Date:
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



Re: [HACKERS] How do I construct a varlena?

From
"Thomas G. Lockhart"
Date:
> 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);
}

Re: [HACKERS] How do I construct a varlena?

From
Maarten Boekhold
Date:
> 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                         |
-----------------------------------------------------------------------------