1999-11-17 22:21:51 +01:00
|
|
|
/* ----------
|
|
|
|
* lztext.c -
|
|
|
|
*
|
1999-11-25 02:28:07 +01:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/lztext.c,v 1.4 1999/11/25 01:28:04 wieck Exp $
|
1999-11-17 22:21:51 +01:00
|
|
|
*
|
|
|
|
* Text type with internal LZ compressed representation. Uses the
|
|
|
|
* standard PostgreSQL compression method.
|
1999-11-17 23:18:46 +01:00
|
|
|
*
|
|
|
|
* This code requires that the LZ compressor found in pg_lzcompress
|
|
|
|
* codes a usable VARSIZE word at the beginning of the output buffer.
|
1999-11-17 22:21:51 +01:00
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "utils/builtins.h"
|
|
|
|
#include "utils/palloc.h"
|
|
|
|
#include "utils/pg_lzcompress.h"
|
1999-11-24 04:45:12 +01:00
|
|
|
#ifdef MULTIBYTE
|
|
|
|
#include "mb/pg_wchar.h"
|
|
|
|
#endif
|
1999-11-17 22:21:51 +01:00
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* lztextin -
|
|
|
|
*
|
|
|
|
* Input function for datatype lztext
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
lztext *
|
|
|
|
lztextin(char *str)
|
|
|
|
{
|
|
|
|
lztext *result;
|
|
|
|
int32 rawsize;
|
|
|
|
lztext *tmp;
|
|
|
|
int tmp_size;
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Handle NULL
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
if (str == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* ----------
|
1999-11-17 23:18:46 +01:00
|
|
|
* Determine input size and maximum output Datum size
|
1999-11-17 22:21:51 +01:00
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
rawsize = strlen(str);
|
|
|
|
tmp_size = PGLZ_MAX_OUTPUT(rawsize);
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Allocate a temporary result and compress into it
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
tmp = (lztext *) palloc(tmp_size);
|
|
|
|
pglz_compress(str, rawsize, tmp, NULL);
|
|
|
|
|
|
|
|
/* ----------
|
1999-11-17 23:18:46 +01:00
|
|
|
* If we miss less than 25% bytes at the end of the temp value,
|
|
|
|
* so be it. Therefore we save a palloc()/memcpy()/pfree()
|
|
|
|
* sequence.
|
1999-11-17 22:21:51 +01:00
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
if (tmp_size - tmp->varsize < 256 ||
|
|
|
|
tmp_size - tmp->varsize < tmp_size / 4)
|
|
|
|
{
|
|
|
|
result = tmp;
|
|
|
|
} else {
|
|
|
|
result = (lztext *) palloc(tmp->varsize);
|
|
|
|
memcpy(result, tmp, tmp->varsize);
|
|
|
|
pfree(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* lztextout -
|
|
|
|
*
|
|
|
|
* Output function for data type lztext
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
lztextout(lztext *lz)
|
|
|
|
{
|
|
|
|
char *result;
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Handle NULL
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
if (lz == NULL)
|
|
|
|
{
|
|
|
|
result = (char *) palloc(2);
|
|
|
|
result[0] = '-';
|
|
|
|
result[1] = '\0';
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Allocate the result string - the required size is remembered
|
|
|
|
* in the lztext header so we don't need a temporary buffer or
|
|
|
|
* have to diddle with realloc's.
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
result = (char *) palloc(PGLZ_RAW_SIZE(lz) + 1);
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Decompress and add terminating ZERO
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
pglz_decompress(lz, result);
|
|
|
|
result[lz->rawsize] = '\0';
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Return the result
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* lztextlen -
|
|
|
|
*
|
|
|
|
* Logical length of lztext field (it's the uncompressed size
|
|
|
|
* of the original data).
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
int32
|
|
|
|
lztextlen(lztext *lz)
|
|
|
|
{
|
1999-11-24 04:45:12 +01:00
|
|
|
#ifdef MULTIBYTE
|
|
|
|
unsigned char *s1,*s2;
|
|
|
|
int len;
|
|
|
|
int l;
|
|
|
|
int wl;
|
|
|
|
#endif
|
1999-11-17 22:21:51 +01:00
|
|
|
/* ----------
|
|
|
|
* Handle NULL
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
if (lz == NULL)
|
|
|
|
return 0;
|
|
|
|
|
1999-11-24 04:45:12 +01:00
|
|
|
#ifdef MULTIBYTE
|
|
|
|
len = 0;
|
|
|
|
s1 = s2 = (unsigned char *)lztextout(lz);
|
|
|
|
l = PGLZ_RAW_SIZE(lz);
|
|
|
|
while (l > 0)
|
|
|
|
{
|
|
|
|
wl = pg_mblen(s1);
|
|
|
|
l -= wl;
|
|
|
|
s1 += wl;
|
|
|
|
len++;
|
|
|
|
}
|
|
|
|
pfree((char *)s2);
|
|
|
|
return (len);
|
|
|
|
#else
|
1999-11-17 22:21:51 +01:00
|
|
|
/* ----------
|
|
|
|
* without multibyte support, it's the remembered rawsize
|
|
|
|
* ----------
|
|
|
|
*/
|
1999-11-17 23:18:46 +01:00
|
|
|
return PGLZ_RAW_SIZE(lz);
|
1999-11-24 04:45:12 +01:00
|
|
|
#endif
|
1999-11-17 22:21:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* lztextoctetlen -
|
|
|
|
*
|
|
|
|
* Physical length of lztext field (it's the compressed size
|
|
|
|
* plus the rawsize field).
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
int32
|
|
|
|
lztextoctetlen(lztext *lz)
|
|
|
|
{
|
|
|
|
/* ----------
|
|
|
|
* Handle NULL
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
if (lz == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Return the varsize minus the VARSIZE field itself.
|
|
|
|
* ----------
|
|
|
|
*/
|
1999-11-17 23:18:46 +01:00
|
|
|
return VARSIZE(lz) - VARHDRSZ;
|
1999-11-17 22:21:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* text_lztext -
|
|
|
|
*
|
|
|
|
* Convert text to lztext
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
lztext *
|
|
|
|
text_lztext(text *txt)
|
|
|
|
{
|
|
|
|
lztext *result;
|
|
|
|
int32 rawsize;
|
|
|
|
lztext *tmp;
|
|
|
|
int tmp_size;
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Handle NULL
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
if (txt == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Determine input size and eventually tuple size
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
rawsize = VARSIZE(txt) - VARHDRSZ;
|
|
|
|
str = VARDATA(txt);
|
|
|
|
tmp_size = PGLZ_MAX_OUTPUT(rawsize);
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Allocate a temporary result and compress into it
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
tmp = (lztext *) palloc(tmp_size);
|
|
|
|
pglz_compress(str, rawsize, tmp, NULL);
|
|
|
|
|
|
|
|
/* ----------
|
1999-11-17 23:18:46 +01:00
|
|
|
* If we miss less than 25% bytes at the end of the temp value,
|
|
|
|
* so be it. Therefore we save a palloc()/memcpy()/pfree()
|
|
|
|
* sequence.
|
1999-11-17 22:21:51 +01:00
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
if (tmp_size - tmp->varsize < 256 ||
|
|
|
|
tmp_size - tmp->varsize < tmp_size / 4)
|
|
|
|
{
|
|
|
|
result = tmp;
|
|
|
|
} else {
|
|
|
|
result = (lztext *) palloc(tmp->varsize);
|
|
|
|
memcpy(result, tmp, tmp->varsize);
|
|
|
|
pfree(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* lztext_text -
|
|
|
|
*
|
|
|
|
* Convert lztext to text
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
text *
|
|
|
|
lztext_text(lztext *lz)
|
|
|
|
{
|
|
|
|
text *result;
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Handle NULL
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
if (lz == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Allocate and initialize the text result
|
|
|
|
* ----------
|
|
|
|
*/
|
1999-11-17 23:18:46 +01:00
|
|
|
result = (text *) palloc(PGLZ_RAW_SIZE(lz) + VARHDRSZ + 1);
|
1999-11-17 22:21:51 +01:00
|
|
|
VARSIZE(result) = lz->rawsize + VARHDRSZ;
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Decompress directly into the text data area.
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
VARDATA(result)[lz->rawsize] = 0;
|
1999-11-17 23:18:46 +01:00
|
|
|
pglz_decompress(lz, VARDATA(result));
|
1999-11-17 22:21:51 +01:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-11-25 02:28:07 +01:00
|
|
|
/* ----------
|
|
|
|
* lztext_cmp -
|
|
|
|
*
|
|
|
|
* Comparision function for two lztext datum's.
|
|
|
|
*
|
|
|
|
* Returns -1, 0 or 1.
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
int32
|
|
|
|
lztext_cmp(lztext *lz1, lztext *lz2)
|
|
|
|
{
|
|
|
|
#ifdef USE_LOCALE
|
|
|
|
|
|
|
|
char *cp1;
|
|
|
|
char *cp2;
|
|
|
|
int result;
|
|
|
|
|
|
|
|
if (lz1 == NULL || lz2 == NULL)
|
|
|
|
return (int32)0;
|
|
|
|
|
|
|
|
cp1 = lztextout(lz1);
|
|
|
|
cp2 = lztextout(lz2);
|
|
|
|
|
|
|
|
result = strcoll(cp1, cp2);
|
|
|
|
|
|
|
|
pfree(cp1);
|
|
|
|
pfree(cp2);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
#else /* !USE_LOCALE */
|
|
|
|
|
|
|
|
PGLZ_DecompState ds1;
|
|
|
|
PGLZ_DecompState ds2;
|
|
|
|
int c1;
|
|
|
|
int c2;
|
|
|
|
int32 result = (int32)0;
|
|
|
|
|
|
|
|
if (lz1 == NULL || lz2 == NULL)
|
|
|
|
return (int32)0;
|
|
|
|
|
|
|
|
pglz_decomp_init(&ds1, lz1);
|
|
|
|
pglz_decomp_init(&ds2, lz2);
|
|
|
|
|
|
|
|
for(;;)
|
|
|
|
{
|
|
|
|
c1 = pglz_decomp_getchar(&ds1);
|
|
|
|
c2 = pglz_decomp_getchar(&ds2);
|
|
|
|
|
|
|
|
if (c1 == EOF)
|
|
|
|
{
|
|
|
|
if (c2 != EOF)
|
|
|
|
result = (int32)-1;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
if (c2 == EOF)
|
|
|
|
{
|
|
|
|
result = (int32)1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (c1 != c2)
|
|
|
|
{
|
|
|
|
result = (int32)(c1 - c2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pglz_decomp_end(&ds1);
|
|
|
|
pglz_decomp_end(&ds2);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
#endif /* USE_LOCALE */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* lztext_eq ... -
|
|
|
|
*
|
|
|
|
* =, !=, >, >=, < and <= operator functions for two
|
|
|
|
* lztext datums.
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
lztext_eq(lztext *lz1, lztext *lz2)
|
|
|
|
{
|
|
|
|
if (lz1 == NULL || lz2 == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return (bool)(lztext_cmp(lz1, lz2) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
lztext_ne(lztext *lz1, lztext *lz2)
|
|
|
|
{
|
|
|
|
if (lz1 == NULL || lz2 == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return (bool)(lztext_cmp(lz1, lz2) != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
lztext_gt(lztext *lz1, lztext *lz2)
|
|
|
|
{
|
|
|
|
if (lz1 == NULL || lz2 == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return (bool)(lztext_cmp(lz1, lz2) > 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
lztext_ge(lztext *lz1, lztext *lz2)
|
|
|
|
{
|
|
|
|
if (lz1 == NULL || lz2 == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return (bool)(lztext_cmp(lz1, lz2) >= 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
lztext_lt(lztext *lz1, lztext *lz2)
|
|
|
|
{
|
|
|
|
if (lz1 == NULL || lz2 == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return (bool)(lztext_cmp(lz1, lz2) < 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
lztext_le(lztext *lz1, lztext *lz2)
|
|
|
|
{
|
|
|
|
if (lz1 == NULL || lz2 == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return (bool)(lztext_cmp(lz1, lz2) <= 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|