Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
P
postgres-lambda-diff
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Jakob Huber
postgres-lambda-diff
Commits
783a7316
Commit
783a7316
authored
18 years ago
by
Teodor Sigaev
Browse files
Options
Downloads
Patches
Plain Diff
Forget to add new file :((
parent
1f7ef548
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/backend/access/gist/gistsplit.c
+538
-0
538 additions, 0 deletions
src/backend/access/gist/gistsplit.c
with
538 additions
and
0 deletions
src/backend/access/gist/gistsplit.c
0 → 100644
+
538
−
0
View file @
783a7316
/*-------------------------------------------------------------------------
*
* gistsplit.c
* Split page algorithm
*
*
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/gist/gistsplit.c,v 1.1 2006/06/28 12:08:35 teodor Exp $
*
*-------------------------------------------------------------------------
*/
#include
"postgres.h"
#include
"access/genam.h"
#include
"access/gist_private.h"
#include
"access/gistscan.h"
#include
"access/heapam.h"
#include
"catalog/index.h"
#include
"commands/vacuum.h"
#include
"miscadmin.h"
#include
"utils/memutils.h"
typedef
struct
{
Datum
*
attr
;
int
len
;
OffsetNumber
*
entries
;
bool
*
isnull
;
bool
*
equiv
;
}
GistSplitUnion
;
/*
* Forms unions of subkeys after page split, but
* uses only tuples aren't in groups of equalent tuples
*/
static
void
gistunionsubkeyvec
(
GISTSTATE
*
giststate
,
IndexTuple
*
itvec
,
GistSplitUnion
*
gsvp
,
int
startkey
)
{
IndexTuple
*
cleanedItVec
;
int
i
,
cleanedLen
=
0
;
cleanedItVec
=
(
IndexTuple
*
)
palloc
(
sizeof
(
IndexTuple
)
*
gsvp
->
len
);
for
(
i
=
0
;
i
<
gsvp
->
len
;
i
++
)
{
if
(
gsvp
->
equiv
&&
gsvp
->
equiv
[
gsvp
->
entries
[
i
]])
continue
;
cleanedItVec
[
cleanedLen
++
]
=
itvec
[
gsvp
->
entries
[
i
]
-
1
];
}
gistMakeUnionItVec
(
giststate
,
cleanedItVec
,
cleanedLen
,
startkey
,
gsvp
->
attr
,
gsvp
->
isnull
);
pfree
(
cleanedItVec
);
}
/*
* unions subkeys for after user picksplit over attno-1 column
*/
static
void
gistunionsubkey
(
GISTSTATE
*
giststate
,
IndexTuple
*
itvec
,
GistSplitVector
*
spl
,
int
attno
)
{
GistSplitUnion
gsvp
;
gsvp
.
equiv
=
spl
->
spl_equiv
;
gsvp
.
attr
=
spl
->
spl_lattr
;
gsvp
.
len
=
spl
->
splitVector
.
spl_nleft
;
gsvp
.
entries
=
spl
->
splitVector
.
spl_left
;
gsvp
.
isnull
=
spl
->
spl_lisnull
;
gistunionsubkeyvec
(
giststate
,
itvec
,
&
gsvp
,
attno
);
gsvp
.
attr
=
spl
->
spl_rattr
;
gsvp
.
len
=
spl
->
splitVector
.
spl_nright
;
gsvp
.
entries
=
spl
->
splitVector
.
spl_right
;
gsvp
.
isnull
=
spl
->
spl_risnull
;
gistunionsubkeyvec
(
giststate
,
itvec
,
&
gsvp
,
attno
);
}
/*
* find group in vector with equivalent value
*/
static
int
gistfindgroup
(
Relation
r
,
GISTSTATE
*
giststate
,
GISTENTRY
*
valvec
,
GistSplitVector
*
spl
,
int
attno
)
{
int
i
;
GISTENTRY
entry
;
int
len
=
0
;
/*
* attno key is always not null (see gistSplitByKey), so we may not check for
* nulls
*/
gistentryinit
(
entry
,
spl
->
splitVector
.
spl_rdatum
,
r
,
NULL
,
(
OffsetNumber
)
0
,
FALSE
);
for
(
i
=
0
;
i
<
spl
->
splitVector
.
spl_nleft
;
i
++
)
{
float
penalty
=
gistpenalty
(
giststate
,
attno
,
&
entry
,
false
,
&
valvec
[
spl
->
splitVector
.
spl_left
[
i
]],
false
);
if
(
penalty
==
0
.
0
)
{
spl
->
spl_equiv
[
spl
->
splitVector
.
spl_left
[
i
]]
=
true
;
len
++
;
}
}
gistentryinit
(
entry
,
spl
->
splitVector
.
spl_ldatum
,
r
,
NULL
,
(
OffsetNumber
)
0
,
FALSE
);
for
(
i
=
0
;
i
<
spl
->
splitVector
.
spl_nright
;
i
++
)
{
float
penalty
=
gistpenalty
(
giststate
,
attno
,
&
entry
,
false
,
&
valvec
[
spl
->
splitVector
.
spl_right
[
i
]],
false
);
if
(
penalty
==
0
.
0
)
{
spl
->
spl_equiv
[
spl
->
splitVector
.
spl_right
[
i
]]
=
true
;
len
++
;
}
}
return
len
;
}
static
void
cleanupOffsets
(
OffsetNumber
*
a
,
int
*
len
,
bool
*
equiv
,
int
*
LenEquiv
)
{
int
curlen
,
i
;
OffsetNumber
*
curwpos
;
curlen
=
*
len
;
curwpos
=
a
;
for
(
i
=
0
;
i
<
*
len
;
i
++
)
{
if
(
equiv
[
a
[
i
]
]
==
FALSE
)
{
*
curwpos
=
a
[
i
];
curwpos
++
;
}
else
{
/* corner case: we shouldn't make void array */
if
(
curlen
==
1
)
{
equiv
[
a
[
i
]
]
=
FALSE
;
/* mark item as non-equivalent */
i
--
;
/* redo the same */
*
LenEquiv
-=
1
;
continue
;
}
else
curlen
--
;
}
}
*
len
=
curlen
;
}
static
void
placeOne
(
Relation
r
,
GISTSTATE
*
giststate
,
GistSplitVector
*
v
,
IndexTuple
itup
,
OffsetNumber
off
,
int
attno
)
{
GISTENTRY
identry
[
INDEX_MAX_KEYS
];
bool
isnull
[
INDEX_MAX_KEYS
];
bool
toLeft
=
true
;
gistDeCompressAtt
(
giststate
,
r
,
itup
,
NULL
,
(
OffsetNumber
)
0
,
identry
,
isnull
);
for
(;
attno
<
giststate
->
tupdesc
->
natts
;
attno
++
)
{
float
lpenalty
,
rpenalty
;
GISTENTRY
entry
;
gistentryinit
(
entry
,
v
->
spl_lattr
[
attno
],
r
,
NULL
,
0
,
FALSE
);
lpenalty
=
gistpenalty
(
giststate
,
attno
,
&
entry
,
v
->
spl_lisnull
[
attno
],
identry
+
attno
,
isnull
[
attno
]);
gistentryinit
(
entry
,
v
->
spl_rattr
[
attno
],
r
,
NULL
,
0
,
FALSE
);
rpenalty
=
gistpenalty
(
giststate
,
attno
,
&
entry
,
v
->
spl_risnull
[
attno
],
identry
+
attno
,
isnull
[
attno
]);
if
(
lpenalty
!=
rpenalty
)
{
if
(
lpenalty
>
rpenalty
)
toLeft
=
false
;
break
;
}
}
if
(
toLeft
)
v
->
splitVector
.
spl_left
[
v
->
splitVector
.
spl_nleft
++
]
=
off
;
else
v
->
splitVector
.
spl_right
[
v
->
splitVector
.
spl_nright
++
]
=
off
;
}
#define SWAPVAR( s, d, t ) \
do { \
(t) = (s); \
(s) = (d); \
(d) = (t); \
} while(0)
/*
* adjust left and right unions according to splits by previous
* split by firsts columns. This function is called only in case
* when pickSplit doesn't support subspplit.
*/
static
void
supportSecondarySplit
(
Relation
r
,
GISTSTATE
*
giststate
,
int
attno
,
GIST_SPLITVEC
*
sv
,
Datum
oldL
,
Datum
oldR
)
{
bool
leaveOnLeft
=
true
,
tmpBool
;
GISTENTRY
entryL
,
entryR
,
entrySL
,
entrySR
;
gistentryinit
(
entryL
,
oldL
,
r
,
NULL
,
0
,
FALSE
);
gistentryinit
(
entryR
,
oldR
,
r
,
NULL
,
0
,
FALSE
);
gistentryinit
(
entrySL
,
sv
->
spl_ldatum
,
r
,
NULL
,
0
,
FALSE
);
gistentryinit
(
entrySR
,
sv
->
spl_rdatum
,
r
,
NULL
,
0
,
FALSE
);
if
(
sv
->
spl_ldatum_exists
&&
sv
->
spl_rdatum_exists
)
{
float
penalty1
,
penalty2
;
penalty1
=
gistpenalty
(
giststate
,
attno
,
&
entryL
,
false
,
&
entrySL
,
false
)
+
gistpenalty
(
giststate
,
attno
,
&
entryR
,
false
,
&
entrySR
,
false
);
penalty2
=
gistpenalty
(
giststate
,
attno
,
&
entryL
,
false
,
&
entrySR
,
false
)
+
gistpenalty
(
giststate
,
attno
,
&
entryR
,
false
,
&
entrySL
,
false
);
if
(
penalty1
>
penalty2
)
leaveOnLeft
=
false
;
}
else
{
GISTENTRY
*
entry1
=
(
sv
->
spl_ldatum_exists
)
?
&
entryL
:
&
entryR
;
float
penalty1
,
penalty2
;
/*
* there is only one previously defined union,
* so we just choose swap or not by lowest penalty
*/
penalty1
=
gistpenalty
(
giststate
,
attno
,
entry1
,
false
,
&
entrySL
,
false
);
penalty2
=
gistpenalty
(
giststate
,
attno
,
entry1
,
false
,
&
entrySR
,
false
);
if
(
penalty1
<
penalty2
)
leaveOnLeft
=
(
sv
->
spl_ldatum_exists
)
?
true
:
false
;
else
leaveOnLeft
=
(
sv
->
spl_rdatum_exists
)
?
true
:
false
;
}
if
(
leaveOnLeft
==
false
)
{
/*
* swap left and right
*/
OffsetNumber
*
off
,
noff
;
Datum
datum
;
SWAPVAR
(
sv
->
spl_left
,
sv
->
spl_right
,
off
);
SWAPVAR
(
sv
->
spl_nleft
,
sv
->
spl_nright
,
noff
);
SWAPVAR
(
sv
->
spl_ldatum
,
sv
->
spl_rdatum
,
datum
);
gistentryinit
(
entrySL
,
sv
->
spl_ldatum
,
r
,
NULL
,
0
,
FALSE
);
gistentryinit
(
entrySR
,
sv
->
spl_rdatum
,
r
,
NULL
,
0
,
FALSE
);
}
if
(
sv
->
spl_ldatum_exists
)
gistMakeUnionKey
(
giststate
,
attno
,
&
entryL
,
false
,
&
entrySL
,
false
,
&
sv
->
spl_ldatum
,
&
tmpBool
);
if
(
sv
->
spl_rdatum_exists
)
gistMakeUnionKey
(
giststate
,
attno
,
&
entryR
,
false
,
&
entrySR
,
false
,
&
sv
->
spl_rdatum
,
&
tmpBool
);
sv
->
spl_ldatum_exists
=
sv
->
spl_rdatum_exists
=
false
;
}
/*
* Calls user picksplit method for attno columns to split vector to
* two vectors. May use attno+n columns data to
* get better split.
* Returns TRUE and v->spl_equiv = NULL if left and right unions of attno columns are the same,
* so caller may find better split
* Returns TRUE and v->spl_equiv != NULL if there is tuples which may be freely moved
*/
static
bool
gistUserPicksplit
(
Relation
r
,
GistEntryVector
*
entryvec
,
int
attno
,
GistSplitVector
*
v
,
IndexTuple
*
itup
,
int
len
,
GISTSTATE
*
giststate
)
{
GIST_SPLITVEC
*
sv
=
&
v
->
splitVector
;
/*
* now let the user-defined picksplit function set up the split vector; in
* entryvec have no null value!!
*/
sv
->
spl_ldatum_exists
=
(
v
->
spl_lisnull
[
attno
]
)
?
false
:
true
;
sv
->
spl_rdatum_exists
=
(
v
->
spl_risnull
[
attno
]
)
?
false
:
true
;
sv
->
spl_ldatum
=
v
->
spl_lattr
[
attno
];
sv
->
spl_rdatum
=
v
->
spl_rattr
[
attno
];
FunctionCall2
(
&
giststate
->
picksplitFn
[
attno
],
PointerGetDatum
(
entryvec
),
PointerGetDatum
(
sv
));
/* compatibility with old code */
if
(
sv
->
spl_left
[
sv
->
spl_nleft
-
1
]
==
InvalidOffsetNumber
)
sv
->
spl_left
[
sv
->
spl_nleft
-
1
]
=
(
OffsetNumber
)
(
entryvec
->
n
-
1
);
if
(
sv
->
spl_right
[
sv
->
spl_nright
-
1
]
==
InvalidOffsetNumber
)
sv
->
spl_right
[
sv
->
spl_nright
-
1
]
=
(
OffsetNumber
)
(
entryvec
->
n
-
1
);
if
(
sv
->
spl_ldatum_exists
||
sv
->
spl_rdatum_exists
)
{
elog
(
LOG
,
"PickSplit method of %d columns of index '%s' doesn't support secondary split"
,
attno
+
1
,
RelationGetRelationName
(
r
)
);
supportSecondarySplit
(
r
,
giststate
,
attno
,
sv
,
v
->
spl_lattr
[
attno
],
v
->
spl_rattr
[
attno
]
);
}
v
->
spl_lattr
[
attno
]
=
sv
->
spl_ldatum
;
v
->
spl_rattr
[
attno
]
=
sv
->
spl_rdatum
;
v
->
spl_lisnull
[
attno
]
=
false
;
v
->
spl_risnull
[
attno
]
=
false
;
/*
* if index is multikey, then we must to try get smaller bounding box for
* subkey(s)
*/
v
->
spl_equiv
=
NULL
;
if
(
giststate
->
tupdesc
->
natts
>
1
&&
attno
+
1
!=
giststate
->
tupdesc
->
natts
)
{
if
(
gistKeyIsEQ
(
giststate
,
attno
,
sv
->
spl_ldatum
,
sv
->
spl_rdatum
)
)
{
/*
* Left and right key's unions are equial, so
* we can get better split by following columns. Note,
* unions for attno columns are already done.
*/
return
true
;
}
else
{
int
LenEquiv
;
v
->
spl_equiv
=
(
bool
*
)
palloc0
(
sizeof
(
bool
)
*
(
entryvec
->
n
+
1
));
LenEquiv
=
gistfindgroup
(
r
,
giststate
,
entryvec
->
vector
,
v
,
attno
);
/*
* if possible, we should distribute equivalent tuples
*/
if
(
LenEquiv
==
0
)
{
gistunionsubkey
(
giststate
,
itup
,
v
,
attno
+
1
);
}
else
{
cleanupOffsets
(
sv
->
spl_left
,
&
sv
->
spl_nleft
,
v
->
spl_equiv
,
&
LenEquiv
);
cleanupOffsets
(
sv
->
spl_right
,
&
sv
->
spl_nright
,
v
->
spl_equiv
,
&
LenEquiv
);
gistunionsubkey
(
giststate
,
itup
,
v
,
attno
+
1
);
if
(
LenEquiv
==
1
)
{
/*
* In case with one tuple we just choose left-right
* by penalty. It's simplify user-defined pickSplit
*/
OffsetNumber
toMove
=
InvalidOffsetNumber
;
for
(
toMove
=
FirstOffsetNumber
;
toMove
<
entryvec
->
n
;
toMove
++
)
if
(
v
->
spl_equiv
[
toMove
]
)
break
;
Assert
(
toMove
<
entryvec
->
n
);
placeOne
(
r
,
giststate
,
v
,
itup
[
toMove
-
1
],
toMove
,
attno
+
1
);
/* redo gistunionsubkey(): it will not degradate performance,
* because it's very rarely */
v
->
spl_equiv
=
NULL
;
gistunionsubkey
(
giststate
,
itup
,
v
,
attno
+
1
);
return
false
;
}
else
if
(
LenEquiv
>
1
)
return
true
;
}
}
}
return
false
;
}
/*
* simple split page
*/
static
void
gistSplitHalf
(
GIST_SPLITVEC
*
v
,
int
len
)
{
int
i
;
v
->
spl_nright
=
v
->
spl_nleft
=
0
;
v
->
spl_left
=
(
OffsetNumber
*
)
palloc
(
len
*
sizeof
(
OffsetNumber
));
v
->
spl_right
=
(
OffsetNumber
*
)
palloc
(
len
*
sizeof
(
OffsetNumber
));
for
(
i
=
1
;
i
<=
len
;
i
++
)
if
(
i
<
len
/
2
)
v
->
spl_right
[
v
->
spl_nright
++
]
=
i
;
else
v
->
spl_left
[
v
->
spl_nleft
++
]
=
i
;
}
/*
* if it was invalid tuple then we need special processing.
* We move all invalid tuples on right page.
*
* if there is no place on left page, gistSplit will be called one more
* time for left page.
*
* Normally, we never exec this code, but after crash replay it's possible
* to get 'invalid' tuples (probability is low enough)
*/
static
void
gistSplitByInvalid
(
GISTSTATE
*
giststate
,
GistSplitVector
*
v
,
IndexTuple
*
itup
,
int
len
)
{
int
i
;
static
OffsetNumber
offInvTuples
[
MaxOffsetNumber
];
int
nOffInvTuples
=
0
;
for
(
i
=
1
;
i
<=
len
;
i
++
)
if
(
GistTupleIsInvalid
(
itup
[
i
-
1
])
)
offInvTuples
[
nOffInvTuples
++
]
=
i
;
if
(
nOffInvTuples
==
len
)
{
/* corner case, all tuples are invalid */
v
->
spl_rightvalid
=
v
->
spl_leftvalid
=
false
;
gistSplitHalf
(
&
v
->
splitVector
,
len
);
}
else
{
GistSplitUnion
gsvp
;
v
->
splitVector
.
spl_right
=
offInvTuples
;
v
->
splitVector
.
spl_nright
=
nOffInvTuples
;
v
->
spl_rightvalid
=
false
;
v
->
splitVector
.
spl_left
=
(
OffsetNumber
*
)
palloc
(
len
*
sizeof
(
OffsetNumber
));
v
->
splitVector
.
spl_nleft
=
0
;
for
(
i
=
1
;
i
<=
len
;
i
++
)
if
(
!
GistTupleIsInvalid
(
itup
[
i
-
1
])
)
v
->
splitVector
.
spl_left
[
v
->
splitVector
.
spl_nleft
++
]
=
i
;
v
->
spl_leftvalid
=
true
;
gsvp
.
equiv
=
NULL
;
gsvp
.
attr
=
v
->
spl_lattr
;
gsvp
.
len
=
v
->
splitVector
.
spl_nleft
;
gsvp
.
entries
=
v
->
splitVector
.
spl_left
;
gsvp
.
isnull
=
v
->
spl_lisnull
;
gistunionsubkeyvec
(
giststate
,
itup
,
&
gsvp
,
0
);
}
}
/*
* trys to split page by attno key, in a case of null
* values move its to separate page.
*/
void
gistSplitByKey
(
Relation
r
,
Page
page
,
IndexTuple
*
itup
,
int
len
,
GISTSTATE
*
giststate
,
GistSplitVector
*
v
,
GistEntryVector
*
entryvec
,
int
attno
)
{
int
i
;
static
OffsetNumber
offNullTuples
[
MaxOffsetNumber
];
int
nOffNullTuples
=
0
;
for
(
i
=
1
;
i
<=
len
;
i
++
)
{
Datum
datum
;
bool
IsNull
;
if
(
!
GistPageIsLeaf
(
page
)
&&
GistTupleIsInvalid
(
itup
[
i
-
1
]))
{
gistSplitByInvalid
(
giststate
,
v
,
itup
,
len
);
return
;
}
datum
=
index_getattr
(
itup
[
i
-
1
],
attno
+
1
,
giststate
->
tupdesc
,
&
IsNull
);
gistdentryinit
(
giststate
,
attno
,
&
(
entryvec
->
vector
[
i
]),
datum
,
r
,
page
,
i
,
FALSE
,
IsNull
);
if
(
IsNull
)
offNullTuples
[
nOffNullTuples
++
]
=
i
;
}
v
->
spl_leftvalid
=
v
->
spl_rightvalid
=
true
;
if
(
nOffNullTuples
==
len
)
{
/*
* Corner case: All keys in attno column are null, we should try to
* split by keys in next column. It all keys in all columns
* are NULL just split page half by half
*/
v
->
spl_risnull
[
attno
]
=
v
->
spl_lisnull
[
attno
]
=
TRUE
;
if
(
attno
+
1
==
r
->
rd_att
->
natts
)
gistSplitHalf
(
&
v
->
splitVector
,
len
);
else
gistSplitByKey
(
r
,
page
,
itup
,
len
,
giststate
,
v
,
entryvec
,
attno
+
1
);
}
else
if
(
nOffNullTuples
>
0
)
{
int
j
=
0
;
/*
* We don't want to mix NULLs and not-NULLs keys
* on one page, so move nulls to right page
*/
v
->
splitVector
.
spl_right
=
offNullTuples
;
v
->
splitVector
.
spl_nright
=
nOffNullTuples
;
v
->
spl_risnull
[
attno
]
=
TRUE
;
v
->
splitVector
.
spl_left
=
(
OffsetNumber
*
)
palloc
(
len
*
sizeof
(
OffsetNumber
));
v
->
splitVector
.
spl_nleft
=
0
;
for
(
i
=
1
;
i
<=
len
;
i
++
)
if
(
j
<
v
->
splitVector
.
spl_nright
&&
offNullTuples
[
j
]
==
i
)
j
++
;
else
v
->
splitVector
.
spl_left
[
v
->
splitVector
.
spl_nleft
++
]
=
i
;
v
->
spl_equiv
=
NULL
;
gistunionsubkey
(
giststate
,
itup
,
v
,
attno
);
}
else
{
/*
* all keys are not-null
*/
entryvec
->
n
=
len
+
1
;
if
(
gistUserPicksplit
(
r
,
entryvec
,
attno
,
v
,
itup
,
len
,
giststate
)
&&
attno
+
1
!=
r
->
rd_att
->
natts
)
{
/*
* Splitting on attno column is not optimized: there is a tuples which can be freely
* left or right page, we will try to split page by
* following columns
*/
if
(
v
->
spl_equiv
==
NULL
)
{
/* simple case: left and right keys for attno column are equial */
gistSplitByKey
(
r
,
page
,
itup
,
len
,
giststate
,
v
,
entryvec
,
attno
+
1
);
}
else
{
/* we should clean up vector from already distributed tuples */
IndexTuple
*
newitup
=
(
IndexTuple
*
)
palloc
((
len
+
1
)
*
sizeof
(
IndexTuple
));
OffsetNumber
*
map
=
(
OffsetNumber
*
)
palloc
((
len
+
1
)
*
sizeof
(
IndexTuple
));
int
newlen
=
0
;
GIST_SPLITVEC
backupSplit
=
v
->
splitVector
;
for
(
i
=
0
;
i
<
len
;
i
++
)
if
(
v
->
spl_equiv
[
i
+
1
]
)
{
map
[
newlen
]
=
i
+
1
;
newitup
[
newlen
++
]
=
itup
[
i
];
}
Assert
(
newlen
>
0
);
backupSplit
.
spl_left
=
(
OffsetNumber
*
)
palloc
(
sizeof
(
OffsetNumber
)
*
len
);
memcpy
(
backupSplit
.
spl_left
,
v
->
splitVector
.
spl_left
,
sizeof
(
OffsetNumber
)
*
v
->
splitVector
.
spl_nleft
);
backupSplit
.
spl_right
=
(
OffsetNumber
*
)
palloc
(
sizeof
(
OffsetNumber
)
*
len
);
memcpy
(
backupSplit
.
spl_right
,
v
->
splitVector
.
spl_right
,
sizeof
(
OffsetNumber
)
*
v
->
splitVector
.
spl_nright
);
gistSplitByKey
(
r
,
page
,
newitup
,
newlen
,
giststate
,
v
,
entryvec
,
attno
+
1
);
/* merge result of subsplit */
for
(
i
=
0
;
i
<
v
->
splitVector
.
spl_nleft
;
i
++
)
backupSplit
.
spl_left
[
backupSplit
.
spl_nleft
++
]
=
map
[
v
->
splitVector
.
spl_left
[
i
]
-
1
];
for
(
i
=
0
;
i
<
v
->
splitVector
.
spl_nright
;
i
++
)
backupSplit
.
spl_right
[
backupSplit
.
spl_nright
++
]
=
map
[
v
->
splitVector
.
spl_right
[
i
]
-
1
];
v
->
splitVector
=
backupSplit
;
/* reunion left and right datums */
gistunionsubkey
(
giststate
,
itup
,
v
,
attno
);
}
}
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment