Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit563a053

Browse files
committed
Fix behavior of ~> (cube, int) operator
~> (cube, int) operator was especially designed for knn-gist search.However, it appears that knn-gist search can't work correctly with currentbehavior of this operator when dataset contains cubes of variabledimensionality. In this case, the same value of second operator argumentcan point to different dimension depending on dimensionality of particular cube.Such behavior is incompatible with gist indexing of cubes, and knn-gist doesn'twork correctly for it.This patch changes behavior of ~> (cube, int) operator by introducing dimensionnumbering where value of second argument unambiguously identifies number ofdimension. With new behavior, this operator can be correctly supported byknn-gist. Relevant changes to cube operator class are also included.Backpatch to v9.6 where operator was introduced.Since behavior of ~> (cube, int) operator is changed, depending entitiesmust be refreshed after upgrade. Such as, expression indexes using thisoperator must be reindexed, materialized views must be rebuilt, storedprocedures and client code must be revised to correctly use new behavior.That should be mentioned in release notes.Noticed by: Tomas VondraAuthor: Alexander KorotkovReviewed by: Tomas Vondra, Andrey BorodinDiscussion:https://www.postgresql.org/message-id/flat/a9657f6a-b497-36ff-e56-482a2c7e3292@2ndquadrant.com
1 parent3c1e9fd commit563a053

File tree

5 files changed

+512
-286
lines changed

5 files changed

+512
-286
lines changed

‎contrib/cube/cube.c

Lines changed: 95 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,15 +1337,55 @@ g_cube_distance(PG_FUNCTION_ARGS)
13371337

13381338
if (strategy==CubeKNNDistanceCoord)
13391339
{
1340+
/*
1341+
* Handle ordering by ~> operator. See comments of cube_coord_llur()
1342+
* for details
1343+
*/
13401344
intcoord=PG_GETARG_INT32(1);
1345+
boolisLeaf=GistPageIsLeaf(entry->page);
13411346

1342-
if (DIM(cube)==0)
1343-
retval=0.0;
1344-
elseif (IS_POINT(cube))
1345-
retval=cube->x[(coord-1) %DIM(cube)];
1347+
/* 0 is the only unsupported coordinate value */
1348+
if (coord <=0)
1349+
ereport(ERROR,
1350+
(errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
1351+
errmsg("cube index %d is out of bounds",coord)));
1352+
1353+
if (coord <=2*DIM(cube))
1354+
{
1355+
/* dimension index */
1356+
intindex= (coord-1) /2;
1357+
/* whether this is upper bound (lower bound otherwise) */
1358+
boolupper= ((coord-1) %2==1);
1359+
1360+
if (IS_POINT(cube))
1361+
{
1362+
retval=cube->x[index];
1363+
}
1364+
else
1365+
{
1366+
if (isLeaf)
1367+
{
1368+
/* For leaf just return required upper/lower bound */
1369+
if (upper)
1370+
retval=Max(cube->x[index],cube->x[index+DIM(cube)]);
1371+
else
1372+
retval=Min(cube->x[index],cube->x[index+DIM(cube)]);
1373+
}
1374+
else
1375+
{
1376+
/*
1377+
* For non-leaf we should always return lower bound,
1378+
* because even upper bound of a child in the subtree can
1379+
* be as small as our lower bound.
1380+
*/
1381+
retval=Min(cube->x[index],cube->x[index+DIM(cube)]);
1382+
}
1383+
}
1384+
}
13461385
else
1347-
retval=Min(cube->x[(coord-1) %DIM(cube)],
1348-
cube->x[(coord-1) %DIM(cube)+DIM(cube)]);
1386+
{
1387+
retval=0.0;
1388+
}
13491389
}
13501390
else
13511391
{
@@ -1492,43 +1532,73 @@ cube_coord(PG_FUNCTION_ARGS)
14921532
}
14931533

14941534

1495-
/*
1496-
* This function works like cube_coord(),
1497-
* but rearranges coordinates of corners to get cube representation
1498-
* in the form of (lower left, upper right).
1499-
* For historical reasons that extension allows us to create cubes in form
1500-
* ((2,1),(1,2)) and instead of normalizing such cube to ((1,1),(2,2)) it
1501-
* stores cube in original way. But to get cubes ordered by one of dimensions
1502-
* directly from the index without extra sort step we need some
1503-
* representation-independent coordinate getter. This function implements it.
1535+
/*----
1536+
* This function works like cube_coord(), but rearranges coordinates in the
1537+
* way suitable to support coordinate ordering using KNN-GiST. For historical
1538+
* reasons this extension allows us to create cubes in form ((2,1),(1,2)) and
1539+
* instead of normalizing such cube to ((1,1),(2,2)) it stores cube in original
1540+
* way. But in order to get cubes ordered by one of dimensions from the index
1541+
* without explicit sort step we need this representation-independent coordinate
1542+
* getter. Moreover, indexed dataset may contain cubes of different dimensions
1543+
* number. Accordingly, this coordinate getter should be able to return
1544+
* lower/upper bound for particular dimension independently on number of cube
1545+
* dimensions.
1546+
*
1547+
* Long story short, this function uses following meaning of coordinates:
1548+
* # (2 * N - 1) -- lower bound of Nth dimension,
1549+
* # (2 * N) -- upper bound of Nth dimension.
1550+
*
1551+
* When given coordinate exceeds number of cube dimensions, then 0 returned
1552+
* (reproducing logic of GiST indexing of variable-length cubes).
15041553
*/
15051554
Datum
15061555
cube_coord_llur(PG_FUNCTION_ARGS)
15071556
{
15081557
NDBOX*cube=PG_GETARG_NDBOX_P(0);
15091558
intcoord=PG_GETARG_INT32(1);
1559+
boolinverse= false;
1560+
float8result;
15101561

1511-
if (coord <=0||coord>2*DIM(cube))
1562+
/* 0 is the only unsupported coordinate value */
1563+
if (coord <=0)
15121564
ereport(ERROR,
15131565
(errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
15141566
errmsg("cube index %d is out of bounds",coord)));
15151567

1516-
if (coord <=DIM(cube))
1568+
if (coord <=2*DIM(cube))
15171569
{
1570+
/* dimension index */
1571+
intindex= (coord-1) /2;
1572+
/* whether this is upper bound (lower bound otherwise) */
1573+
boolupper= ((coord-1) %2==1);
1574+
15181575
if (IS_POINT(cube))
1519-
PG_RETURN_FLOAT8(cube->x[coord-1]);
1576+
{
1577+
result=cube->x[index];
1578+
}
15201579
else
1521-
PG_RETURN_FLOAT8(Min(cube->x[coord-1],
1522-
cube->x[coord-1+DIM(cube)]));
1580+
{
1581+
if (upper)
1582+
result=Max(cube->x[index],cube->x[index+DIM(cube)]);
1583+
else
1584+
result=Min(cube->x[index],cube->x[index+DIM(cube)]);
1585+
}
15231586
}
15241587
else
15251588
{
1526-
if (IS_POINT(cube))
1527-
PG_RETURN_FLOAT8(cube->x[(coord-1) %DIM(cube)]);
1528-
else
1529-
PG_RETURN_FLOAT8(Max(cube->x[coord-1],
1530-
cube->x[coord-1-DIM(cube)]));
1589+
/*
1590+
* Return zero if coordinate is out of bound. That reproduces logic of
1591+
* how cubes with low dimension number are expanded during GiST
1592+
* indexing.
1593+
*/
1594+
result=0.0;
15311595
}
1596+
1597+
/* Inverse value if needed */
1598+
if (inverse)
1599+
result=-result;
1600+
1601+
PG_RETURN_FLOAT8(result);
15321602
}
15331603

15341604
/* Increase or decrease box size by a radius in at least n dimensions. */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp