postgresqlubuntugithubmakefile

How to set "VARSIZE" and "SET_VARSIZE" in PostgreSQL 16


I'm trying to build the mapnik-german-l10n on Ubuntu 22.04 but got the following error:

https://github.com/giggls/mapnik-german-l10n/blob/master/icutranslit/osml10n_translit.cpp

Here is the error:

make -C icutranslit
make[1]: Entering directory '/home/test/mapnik-german-l10n-master/icutranslit'
g++ -fpic -fno-exceptions -I/usr/include/postgresql/16/server -c osml10n_translit.cpp
osml10n_translit.cpp: In function ‘Datum osml10n_translit(FunctionCallInfo)’:
osml10n_translit.cpp:46:26: error: ‘VARSIZE’ was not declared in this scope
   46 |   inbuf=(char *) malloc((VARSIZE(t) - VARHDRSZ +1)*sizeof(char));
      |                          ^~~~~~~
osml10n_translit.cpp:47:26: error: ‘VARDATA’ was not declared in this scope
   47 |   memcpy(inbuf, (void *) VARDATA(t), VARSIZE(t) - VARHDRSZ);
      |                          ^~~~~~~
osml10n_translit.cpp:72:3: error: ‘SET_VARSIZE’ was not declared in this scope
   72 |   SET_VARSIZE(new_text, VARHDRSZ + bufLen);
      |   ^~~~~~~~~~~
make[1]: *** [Makefile:13: osml10n_translit.o] Error 1
make[1]: Leaving directory '/home/test/mapnik-german-l10n-master/icutranslit'
make: *** [Makefile:30: icutranslit] Error 2

Here is the source code:

/* needed in icu >= 62 */
#define U_USING_ICU_NAMESPACE 1

#include <iostream>
#include <unicode/unistr.h>
#include <unicode/translit.h>

extern "C" {

#include <postgres.h>
#include <stdlib.h>
#include <string.h>
#include <mb/pg_wchar.h>
#include <fmgr.h>

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

PG_FUNCTION_INFO_V1(osml10n_translit);

Datum osml10n_translit(PG_FUNCTION_ARGS) {
  Transliterator *latin_tl;
  UErrorCode status = U_ZERO_ERROR;
  char *inbuf,*outbuf;
  
  if (GetDatabaseEncoding() != PG_UTF8) {
    ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    errmsg("requires UTF8 database encoding")));
  }
   
  text *t = PG_GETARG_TEXT_P(0);

  inbuf=(char *) malloc((VARSIZE(t) - VARHDRSZ +1)*sizeof(char));
  memcpy(inbuf, (void *) VARDATA(t), VARSIZE(t) - VARHDRSZ);
  inbuf[VARSIZE(t) - VARHDRSZ]='\0';
   
  UnicodeString ustr(inbuf);
  latin_tl = Transliterator::createInstance("Any-Latin", UTRANS_FORWARD, status);
  if (latin_tl == 0) {
    ereport(ERROR,(errcode(ERRCODE_SYSTEM_ERROR),
    errmsg("ERROR: Transliterator::createInstance() failed")));
    PG_RETURN_TEXT_P("");
  }
  latin_tl->transliterate(ustr);
  
  
  int32_t bufLen = 100;
  outbuf = (char *) malloc((bufLen + 1)*sizeof(char));
  status=U_ZERO_ERROR;
  bufLen = ustr.extract(outbuf,bufLen,NULL,status);
  if (status == U_BUFFER_OVERFLOW_ERROR) {
    status=U_ZERO_ERROR;
    outbuf = (char *) realloc(outbuf, bufLen + 1);
    bufLen = ustr.extract(outbuf,bufLen,NULL,status);
  }
  outbuf[bufLen] = '\0'; 
  
  text *new_text = (text *) palloc(VARHDRSZ + bufLen);
  SET_VARSIZE(new_text, VARHDRSZ + bufLen);
  memcpy((void *) VARDATA(new_text), /* destination */
         (void *) outbuf,bufLen);
  
  free(inbuf);
  free(outbuf);
  delete latin_tl;       
  PG_RETURN_TEXT_P(new_text);
}

} /* extern "C" */

I have tried to search in postgres.h but found nothing:

/usr/include/postgresql/16/server/postgres.h

Which library contains this "VARSIZE" and "SET_VARSIZE"?

Update:

I found that /usr/include/postgresql/15/server/postgres.h contains the "VARSIZE" and "SET_VARSIZE", but the /usr/include/postgresql/16/server/postgres.h does not.

Here is the source code of /usr/include/postgresql/15/server/postgres.h

/* ----------------------------------------------------------------
 *              Section 1:  variable-length datatypes (TOAST support)
 * ----------------------------------------------------------------
 */
...
/*
 * In consumers oblivious to data alignment, call PG_DETOAST_DATUM_PACKED(),
 * VARDATA_ANY(), VARSIZE_ANY() and VARSIZE_ANY_EXHDR().  Elsewhere, call
 * PG_DETOAST_DATUM(), VARDATA() and VARSIZE().  Directly fetching an int16,
 * int32 or wider field in the struct representing the datum layout requires
 * aligned data.  memcpy() is alignment-oblivious, as are most operations on
 * datatypes, such as text, whose layout struct contains only char fields.
 *
 * Code assembling a new datum should call VARDATA() and SET_VARSIZE().
 * (Datums begin life untoasted.)
 *
 * Other macros here should usually be used only by tuple assembly/disassembly
 * code and code that specifically wants to work with still-toasted Datums.
 */
#define VARDATA(PTR)                        VARDATA_4B(PTR)
#define VARSIZE(PTR)                        VARSIZE_4B(PTR)

#define VARSIZE_SHORT(PTR)                  VARSIZE_1B(PTR)
#define VARDATA_SHORT(PTR)                  VARDATA_1B(PTR)

#define VARTAG_EXTERNAL(PTR)                VARTAG_1B_E(PTR)
#define VARSIZE_EXTERNAL(PTR)               (VARHDRSZ_EXTERNAL + VARTAG_SIZE(VARTAG_EXTERNAL(PTR)))
#define VARDATA_EXTERNAL(PTR)               VARDATA_1B_E(PTR)
...

/* ----------------------------------------------------------------
 *              Section 2:  Datum type + support macros
 * ----------------------------------------------------------------
 */
...
typedef uintptr_t Datum;

/*
 * A NullableDatum is used in places where both a Datum and its nullness needs
 * to be stored. This can be more efficient than storing datums and nullness
 * in separate arrays, due to better spatial locality, even if more space may
 * be wasted due to padding.
 */
typedef struct NullableDatum
{
#define FIELDNO_NULLABLE_DATUM_DATUM 0
    Datum       value;
#define FIELDNO_NULLABLE_DATUM_ISNULL 1
    bool        isnull;
    /* due to alignment padding this could be used for flags for free */
} NullableDatum;
...

Here is the source code of /usr/include/postgresql/16/server/postgres.h

/* ----------------------------------------------------------------
 *              Section 1:  Datum type + support functions
 * ----------------------------------------------------------------
 */

/*
 * A Datum contains either a value of a pass-by-value type or a pointer to a
 * value of a pass-by-reference type.  Therefore, we require:
 *
 * sizeof(Datum) == sizeof(void *) == 4 or 8
 *
 * The functions below and the analogous functions for other types should be used to
 * convert between a Datum and the appropriate C type.
 */

typedef uintptr_t Datum;

/*
 * A NullableDatum is used in places where both a Datum and its nullness needs
 * to be stored. This can be more efficient than storing datums and nullness
 * in separate arrays, due to better spatial locality, even if more space may
 * be wasted due to padding.
 */
typedef struct NullableDatum
{
#define FIELDNO_NULLABLE_DATUM_DATUM 0
    Datum       value;
#define FIELDNO_NULLABLE_DATUM_ISNULL 1
    bool        isnull;
    /* due to alignment padding this could be used for flags for free */
} NullableDatum;

It seems that "postgresql 16" has removed the "Section 1: variable-length datatypes (TOAST support)" from the postgres.h.

How to set "VARSIZE" and "SET_VARSIZE" in "osml10n_translit.cpp" for making it to work in postgresql 16?


Solution

  • PostgreSQL v16 moved these definitions to server/varatt.h in commit d952373a98. So you have to

    #include "varatt.h"
    

    to get these macros from v16 on.