Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1219,19 +1219,19 @@ SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE
SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a < ANY (ARRAY[1, 51]) AND b > ''1''');
estimated | actual
-----------+--------
1815 | 2400
2551 | 2400
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a >= ANY (ARRAY[1, 51]) AND b <= ANY (ARRAY[''1'', ''2''])');
estimated | actual
-----------+--------
4801 | 1250
1301 | 1250
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a <= ANY (ARRAY[1, 2, 51, 52]) AND b >= ANY (ARRAY[''1'', ''2''])');
estimated | actual
-----------+--------
1133 | 2550
2651 | 2550
(1 row)

-- ALL (should not benefit from functional dependencies)
Expand Down Expand Up @@ -1385,19 +1385,19 @@ SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE
SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a < ANY (ARRAY[1, 51]) AND b > ''1''');
estimated | actual
-----------+--------
1815 | 2400
2551 | 2400
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a >= ANY (ARRAY[1, 51]) AND b <= ANY (ARRAY[''1'', ''2''])');
estimated | actual
-----------+--------
4801 | 1250
1301 | 1250
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a <= ANY (ARRAY[1, 2, 51, 52]) AND b >= ANY (ARRAY[''1'', ''2''])');
estimated | actual
-----------+--------
1133 | 2550
2651 | 2550
(1 row)

-- ALL (should not benefit from functional dependencies)
Expand Down Expand Up @@ -1944,25 +1944,25 @@ SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE 1 = a AND ''1'
SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a < 1 AND b < ''1''');
estimated | actual
-----------+--------
36 | 50
2 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE 1 > a AND ''1'' > b');
estimated | actual
-----------+--------
36 | 50
2 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a <= 0 AND b <= ''0''');
estimated | actual
-----------+--------
36 | 50
2 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE 0 >= a AND ''0'' >= b');
estimated | actual
-----------+--------
36 | 50
2 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 AND b = ''1'' AND c = 1');
Expand All @@ -1974,25 +1974,25 @@ SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 AND b =
SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a < 5 AND b < ''1'' AND c < 5');
estimated | actual
-----------+--------
85 | 50
5 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a < 5 AND ''1'' > b AND 5 > c');
estimated | actual
-----------+--------
85 | 50
5 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a <= 4 AND b <= ''0'' AND c <= 4');
estimated | actual
-----------+--------
85 | 50
5 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE 4 >= a AND ''0'' >= b AND 4 >= c');
estimated | actual
-----------+--------
85 | 50
5 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 OR b = ''1'' OR c = 1');
Expand Down Expand Up @@ -2085,25 +2085,25 @@ SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE 1 = a AND ''1'
SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a < 1 AND b < ''1''');
estimated | actual
-----------+--------
36 | 50
2 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE 1 > a AND ''1'' > b');
estimated | actual
-----------+--------
36 | 50
2 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a <= 0 AND b <= ''0''');
estimated | actual
-----------+--------
36 | 50
2 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE 0 >= a AND ''0'' >= b');
estimated | actual
-----------+--------
36 | 50
2 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 AND b = ''1'' AND c = 1');
Expand All @@ -2115,25 +2115,25 @@ SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 AND b =
SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a < 5 AND b < ''1'' AND c < 5');
estimated | actual
-----------+--------
85 | 50
5 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a < 5 AND ''1'' > b AND 5 > c');
estimated | actual
-----------+--------
85 | 50
5 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a <= 4 AND b <= ''0'' AND c <= 4');
estimated | actual
-----------+--------
85 | 50
5 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE 4 >= a AND ''0'' >= b AND 4 >= c');
estimated | actual
-----------+--------
85 | 50
5 | 50
(1 row)

SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 OR b = ''1'' OR c = 1');
Expand Down
131 changes: 131 additions & 0 deletions src/backend/gpopt/gpdbwrappers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ extern "C" {
#include "catalog/pg_inherits.h"
#include "cdb/cdbvars.h"
#include "foreign/fdwapi.h"
#include "mb/pg_wchar.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/optimizer.h"
Expand All @@ -56,10 +57,13 @@ extern "C" {
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/partcache.h"
#include "utils/pg_locale.h"

extern bool enable_parallel;
extern int max_parallel_workers_per_gather;

}

#define GP_WRAP_START \
sigjmp_buf local_sigjmp_buf; \
{ \
Expand Down Expand Up @@ -2450,6 +2454,133 @@ gpdb::MakeGpPolicy(GpPolicyType ptype, int nattrs, int numsegments)
GP_WRAP_END;
}

size_t
gpdb::ComputeLocaleSortKey(char *dest, size_t destsize, const char *src,
size_t srclen, Oid collation)
{
GP_WRAP_START;
{
if (destsize == 0)
{
return 0;
}

// C/POSIX collation: byte order already matches sort order, just copy.
// Treat InvalidOid the same way (no collation info available).
if (!OidIsValid(collation) || lc_collate_is_c(collation))
{
size_t n = (srclen < destsize) ? srclen : destsize;
memcpy(dest, src, n);
return n;
}

pg_locale_t locale = pg_newlocale_from_collation(collation);

// Non-deterministic collations (case/accent-insensitive ICU) don't
// produce a totally-ordered sort key for our purposes; bail.
if (locale != NULL && !locale->deterministic)
{
return 0;
}

#ifdef USE_ICU
if (locale != NULL && locale->provider == COLLPROVIDER_ICU)
{
// Best path for UTF-8 databases: ICU iterator gives us exactly
// the prefix we want without computing the full sort key.
if (GetDatabaseEncoding() == PG_UTF8)
{
UCharIterator iter;
uint32_t state[2] = {0, 0};
UErrorCode status = U_ZERO_ERROR;
uiter_setUTF8(&iter, src, (int32_t) srclen);
int32_t bsize = ucol_nextSortKeyPart(
locale->info.icu.ucol, &iter, state,
(uint8_t *) dest, (int32_t) destsize, &status);
if (U_FAILURE(status))
{
return 0;
}
return (size_t) bsize;
}
// Non-UTF8 ICU: skip the conversion dance; caller falls back.
return 0;
}
#endif

// libc path: strxfrm[_l] needs a NUL-terminated input and an output
// buffer big enough to hold the full transform (the C standard
// leaves dest indeterminate if the result didn't fit). Allocate a
// big-enough work buffer, then copy the prefix we actually need.
char nullterm_stack[256];
char *nullterm = nullterm_stack;
if (srclen + 1 > sizeof(nullterm_stack))
{
nullterm = (char *) palloc(srclen + 1);
}
memcpy(nullterm, src, srclen);
nullterm[srclen] = '\0';

char xfrm_stack[1024];
char *xfrm = xfrm_stack;
size_t xfrm_size = sizeof(xfrm_stack);
size_t bsize;
for (;;)
{
#ifdef HAVE_LOCALE_T
if (locale != NULL && locale->provider == COLLPROVIDER_LIBC)
{
bsize =
strxfrm_l(xfrm, nullterm, xfrm_size, locale->info.lt);
}
else
#endif
{
bsize = strxfrm(xfrm, nullterm, xfrm_size);
}
if (bsize < xfrm_size)
{
break;
}
// grow and retry; cap to avoid runaway allocations.
if (xfrm_size >= (size_t) 64 * 1024)
{
if (xfrm != xfrm_stack)
{
pfree(xfrm);
}
if (nullterm != nullterm_stack)
{
pfree(nullterm);
}
return 0;
}
if (xfrm != xfrm_stack)
{
pfree(xfrm);
}
xfrm_size = (bsize + 1 > xfrm_size * 2) ? bsize + 1
: xfrm_size * 2;
xfrm = (char *) palloc(xfrm_size);
}

size_t out = (bsize < destsize) ? bsize : destsize;
memcpy(dest, xfrm, out);

if (xfrm != xfrm_stack)
{
pfree(xfrm);
}
if (nullterm != nullterm_stack)
{
pfree(nullterm);
}
return out;
}
GP_WRAP_END;
return 0;
}

uint32
gpdb::HashChar(Datum d)
{
Expand Down
Loading
Loading