Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
bddbccd5
Commit
bddbccd5
authored
2 years ago
by
Abuhujair Javed
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Functional Dependency
parent
9c5cbed9
REL_14_STABLE
No related merge requests found
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
332 additions
and
10 deletions
+332
-10
.gitignore
.gitignore
+7
-0
configure
configure
+6
-6
src/backend/access/nbtree/nbtinsert.c
src/backend/access/nbtree/nbtinsert.c
+53
-4
src/backend/access/nbtree/nbtsearch.c
src/backend/access/nbtree/nbtsearch.c
+144
-0
src/backend/access/nbtree/nbtutils.c
src/backend/access/nbtree/nbtutils.c
+116
-0
src/include/access/nbtree.h
src/include/access/nbtree.h
+6
-0
No files found.
.gitignore
View file @
bddbccd5
...
...
@@ -42,3 +42,10 @@ lib*.pc
/Debug/
/Release/
/tmp_install/
.cproject
.project
gmake.out
gmake_install.out
install*
logfile
This diff is collapsed.
Click to expand it.
configure
View file @
bddbccd5
...
...
@@ -4332,13 +4332,13 @@ if test "$ac_test_CFLAGS" = set; then
CFLAGS
=
$ac_save_CFLAGS
elif
test
$ac_cv_prog_cc_g
=
yes
;
then
if
test
"
$GCC
"
=
yes
;
then
CFLAGS
=
"-g -O
2
"
CFLAGS
=
"-g -O
0
"
else
CFLAGS
=
"-g"
fi
else
if
test
"
$GCC
"
=
yes
;
then
CFLAGS
=
"-O
2
"
CFLAGS
=
"-O
0
"
else
CFLAGS
=
fi
...
...
@@ -4863,13 +4863,13 @@ if test "$ac_test_CXXFLAGS" = set; then
CXXFLAGS
=
$ac_save_CXXFLAGS
elif
test
$ac_cv_prog_cxx_g
=
yes
;
then
if
test
"
$GXX
"
=
yes
;
then
CXXFLAGS
=
"-g -O
2
"
CXXFLAGS
=
"-g -O
0
"
else
CXXFLAGS
=
"-g"
fi
else
if
test
"
$GXX
"
=
yes
;
then
CXXFLAGS
=
"-O
2
"
CXXFLAGS
=
"-O
0
"
else
CXXFLAGS
=
fi
...
...
@@ -5227,7 +5227,7 @@ elif test "${CFLAGS+set}" = set; then
elif
test
"
$enable_coverage
"
=
yes
;
then
:
# no optimization by default
elif
test
"
$GCC
"
=
yes
;
then
CFLAGS
=
"-O
2
"
CFLAGS
=
"-O
0
"
else
# if the user selected debug mode, don't use -O
if
test
"
$enable_debug
"
!=
yes
;
then
...
...
@@ -5242,7 +5242,7 @@ elif test "${CXXFLAGS+set}" = set; then
elif
test
"
$enable_coverage
"
=
yes
;
then
:
# no optimization by default
elif
test
"
$GCC
"
=
yes
;
then
CXXFLAGS
=
"-O
2
"
CXXFLAGS
=
"-O
0
"
else
# if the user selected debug mode, don't use -O
if
test
"
$enable_debug
"
!=
yes
;
then
...
...
This diff is collapsed.
Click to expand it.
src/backend/access/nbtree/nbtinsert.c
View file @
bddbccd5
...
...
@@ -106,6 +106,12 @@ _bt_doinsert(Relation rel, IndexTuple itup,
BTStack
stack
;
bool
checkingunique
=
(
checkUnique
!=
UNIQUE_CHECK_NO
);
/* CS631 Start */
Oid
special
=
32788
;
bool
checkingfd
=
false
;
if
(
rel
->
rd_index
->
indexrelid
==
special
)
checkingfd
=
true
;
/* CS631 End */
/* we need an insertion scan key to do our search, so build one */
itup_key
=
_bt_mkscankey
(
rel
,
itup
);
...
...
@@ -199,7 +205,10 @@ search:
* let the tuple in and return false for possibly non-unique, or true for
* definitely unique.
*/
if
(
checkingunique
)
/* CS631 Start */
if
(
checkingunique
||
checkingfd
)
/* CS631 End */
{
TransactionId
xwait
;
uint32
speculativeToken
;
...
...
@@ -421,6 +430,13 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel,
bool
prevalldead
=
true
;
int
curposti
=
0
;
/* CS631 Start */
Oid
special
=
32788
;
bool
checkfd
=
false
;
if
(
rel
->
rd_index
->
indexrelid
==
special
)
checkfd
=
true
;
/* CS631 End */
/* Assume unique until we find a duplicate */
*
is_unique
=
true
;
...
...
@@ -506,10 +522,17 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel,
if
(
!
inposting
)
{
/* CS631 Start */
if
(
checkfd
){
if
(
_bt_compare_fd
(
rel
,
itup
,
itup_key
,
page
,
offset
)
!=
0
)
break
;
}
if
(
checkUnique
){
/* Plain tuple, or first TID in posting list tuple */
if
(
_bt_compare
(
rel
,
itup_key
,
page
,
offset
)
!=
0
)
break
;
/* we're past all the equal tuples */
if
(
_bt_compare
(
rel
,
itup_key
,
page
,
offset
)
!=
0
)
break
;
/* we're past all the equal tuples */
}
/* CS631 End */
/* Advanced curitup */
curitup
=
(
IndexTuple
)
PageGetItem
(
page
,
curitemid
);
Assert
(
!
BTreeTupleIsPivot
(
curitup
));
...
...
@@ -649,6 +672,8 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel,
insertstate
->
buf
=
InvalidBuffer
;
insertstate
->
bounds_valid
=
false
;
/* CS631 Start */
if
(
checkUnique
)
{
Datum
values
[
INDEX_MAX_KEYS
];
bool
isnull
[
INDEX_MAX_KEYS
];
...
...
@@ -669,6 +694,30 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel,
errtableconstraint
(
heapRel
,
RelationGetRelationName
(
rel
))));
}
if
(
checkfd
)
{
Datum
values
[
INDEX_MAX_KEYS
];
bool
isnull
[
INDEX_MAX_KEYS
];
char
*
key_desc
;
index_deform_tuple
(
itup
,
RelationGetDescr
(
rel
),
values
,
isnull
);
key_desc
=
BuildIndexValueDescription
(
rel
,
values
,
isnull
);
ereport
(
ERROR
,
(
errcode
(
ERRCODE_UNIQUE_VIOLATION
),
errmsg
(
"Functional Dependency violated fd constraint
\"
%s
\"
"
,
RelationGetRelationName
(
rel
)),
key_desc
?
errdetail
(
"Functional Dependency not preserving for key: %s."
,
key_desc
)
:
0
,
errtableconstraint
(
heapRel
,
RelationGetRelationName
(
rel
))));
}
/* CS631 End */
}
else
if
(
all_dead
&&
(
!
inposting
||
(
prevalldead
&&
...
...
This diff is collapsed.
Click to expand it.
src/backend/access/nbtree/nbtsearch.c
View file @
bddbccd5
...
...
@@ -671,6 +671,7 @@ _bt_compare(Relation rel,
int
ncmpkey
;
int
ntupatts
;
int32
result
;
Oid
special
=
32788
;
Assert
(
_bt_check_natts
(
rel
,
key
->
heapkeyspace
,
page
,
offnum
));
Assert
(
key
->
keysz
<=
IndexRelationGetNumberOfKeyAttributes
(
rel
));
...
...
@@ -751,6 +752,10 @@ _bt_compare(Relation rel,
scankey
++
;
}
if
(
rel
->
rd_index
->
indexrelid
==
special
){
return
0
;
}
/*
* All non-truncated attributes (other than heap TID) were found to be
* equal. Treat truncated attributes as minus infinity when scankey has a
...
...
@@ -2499,3 +2504,142 @@ _bt_initialize_more_data(BTScanOpaque so, ScanDirection dir)
so
->
numKilled
=
0
;
/* just paranoia */
so
->
markItemIndex
=
-
1
;
/* ditto */
}
/* CS631 Start */
/*----------
* _bt_compare_fd() -- Compare insertion-type scankey to tuple on a page.
*
* page/offnum: location of btree item to be compared to.
*
* This routine returns:
* <0 if scankey < tuple at offnum;
* 0 if scankey == tuple at offnum;
* >0 if scankey > tuple at offnum.
*
* NULLs in the keys are treated as sortable values. Therefore
* "equality" does not necessarily mean that the item should be returned
* to the caller as a matching key. Similarly, an insertion scankey
* with its scantid set is treated as equal to a posting tuple whose TID
* range overlaps with their scantid. There generally won't be a
* matching TID in the posting tuple, which caller must handle
* themselves (e.g., by splitting the posting list tuple).
*
* CRUCIAL NOTE: on a non-leaf page, the first data key is assumed to be
* "minus infinity": this routine will always claim it is less than the
* scankey. The actual key value stored is explicitly truncated to 0
* attributes (explicitly minus infinity) with version 3+ indexes, but
* that isn't relied upon. This allows us to implement the Lehman and
* Yao convention that the first down-link pointer is before the first
* key. See backend/access/nbtree/README for details.
*----------
*/
int32
_bt_compare_fd
(
Relation
rel
,
IndexTuple
itup_
,
BTScanInsert
key
,
Page
page
,
OffsetNumber
offnum
)
{
TupleDesc
itupdesc
=
RelationGetDescr
(
rel
);
BTPageOpaque
opaque
=
(
BTPageOpaque
)
PageGetSpecialPointer
(
page
);
IndexTuple
itup
;
// ItemPointer heapTid;
ScanKey
scankey
;
int
ncmpkey
;
int
ntupatts
;
int32
result
;
// BTScanInsert nonkey;
// ScanKey scannonkey;
Assert
(
_bt_check_natts
(
rel
,
key
->
heapkeyspace
,
page
,
offnum
));
Assert
(
key
->
keysz
<=
IndexRelationGetNumberOfKeyAttributes
(
rel
));
Assert
(
key
->
heapkeyspace
||
key
->
scantid
==
NULL
);
/*
* Force result ">" if target item is first data item on an internal page
* --- see NOTE above.
*/
if
(
!
P_ISLEAF
(
opaque
)
&&
offnum
==
P_FIRSTDATAKEY
(
opaque
))
return
1
;
itup
=
(
IndexTuple
)
PageGetItem
(
page
,
PageGetItemId
(
page
,
offnum
));
ntupatts
=
BTreeTupleGetNAtts
(
itup
,
rel
);
/*
* The scan key is set up with the attribute number associated with each
* term in the key. It is important that, if the index is multi-key, the
* scan contain the first k key attributes, and that they be in order. If
* you think about how multi-key ordering works, you'll understand why
* this is.
*
* We don't test for violation of this condition here, however. The
* initial setup for the index scan had better have gotten it right (see
* _bt_first).
*/
ncmpkey
=
Min
(
ntupatts
,
key
->
keysz
);
Assert
(
key
->
heapkeyspace
||
ncmpkey
==
key
->
keysz
);
Assert
(
!
BTreeTupleIsPosting
(
itup
)
||
key
->
allequalimage
);
scankey
=
key
->
scankeys
;
for
(
int
i
=
1
;
i
<=
ncmpkey
;
i
++
)
{
Datum
datum
;
bool
isNull
;
datum
=
index_getattr
(
itup
,
scankey
->
sk_attno
,
itupdesc
,
&
isNull
);
/*
* The sk_func needs to be passed the index value as left arg and
* the sk_argument as right arg (they might be of different
* types). Since it is convenient for callers to think of
* _bt_compare as comparing the scankey to the index item, we have
* to flip the sign of the comparison result. (Unless it's a DESC
* column, in which case we *don't* flip the sign.)
*/
result
=
DatumGetInt32
(
FunctionCall2Coll
(
&
scankey
->
sk_func
,
scankey
->
sk_collation
,
datum
,
scankey
->
sk_argument
));
/* if the keys are unequal, return the difference */
if
(
result
!=
0
){
result
=
1
;
return
result
;
}
scankey
++
;
}
// nonkey = _bt_mkscankey_nonkey(rel, itup_);
// scannonkey = nonkey->scankeys;
scankey
=
key
->
scankeys
;
for
(
int
i
=
ncmpkey
+
1
;
i
<=
ntupatts
;
i
++
)
{
Datum
datum1
;
Datum
datum2
;
bool
isNull
;
datum1
=
index_getattr
(
itup
,
i
,
itupdesc
,
&
isNull
);
datum2
=
index_getattr
(
itup_
,
i
,
itupdesc
,
&
isNull
);
result
=
DatumGetInt32
(
FunctionCall2Coll
(
&
scankey
->
sk_func
,
scankey
->
sk_collation
,
datum1
,
datum2
));
/* if the keys are unequal, return the difference */
if
(
result
!=
0
){
result
=
0
;
return
result
;
}
scankey
++
;
}
if
(
result
==
0
){
result
=
1
;
return
result
;
}
}
/* CS631 End */
This diff is collapsed.
Click to expand it.
src/backend/access/nbtree/nbtutils.c
View file @
bddbccd5
...
...
@@ -2749,3 +2749,119 @@ _bt_allequalimage(Relation rel, bool debugmessage)
return
allequalimage
;
}
/* CS631 Start */
/*
* _bt_mkscankey
* Build an insertion scan key that contains comparison data from itup
* as well as comparator routines appropriate to the key datatypes.
*
* When itup is a non-pivot tuple, the returned insertion scan key is
* suitable for finding a place for it to go on the leaf level. Pivot
* tuples can be used to re-find leaf page with matching high key, but
* then caller needs to set scan key's pivotsearch field to true. This
* allows caller to search for a leaf page with a matching high key,
* which is usually to the left of the first leaf page a non-pivot match
* might appear on.
*
* The result is intended for use with _bt_compare() and _bt_truncate().
* Callers that don't need to fill out the insertion scankey arguments
* (e.g. they use an ad-hoc comparison routine, or only need a scankey
* for _bt_truncate()) can pass a NULL index tuple. The scankey will
* be initialized as if an "all truncated" pivot tuple was passed
* instead.
*
* Note that we may occasionally have to share lock the metapage to
* determine whether or not the keys in the index are expected to be
* unique (i.e. if this is a "heapkeyspace" index). We assume a
* heapkeyspace index when caller passes a NULL tuple, allowing index
* build callers to avoid accessing the non-existent metapage. We
* also assume that the index is _not_ allequalimage when a NULL tuple
* is passed; CREATE INDEX callers call _bt_allequalimage() to set the
* field themselves.
*/
BTScanInsert
_bt_mkscankey_nonkey
(
Relation
rel
,
IndexTuple
itup
)
{
BTScanInsert
key
;
ScanKey
skey
;
TupleDesc
itupdesc
;
int
indnkeyatts
;
int16
*
indoption
;
int
tupnatts
;
int
i
;
itupdesc
=
RelationGetDescr
(
rel
);
indnkeyatts
=
IndexRelationGetNumberOfKeyAttributes
(
rel
);
indoption
=
rel
->
rd_indoption
;
tupnatts
=
itup
?
BTreeTupleGetNAtts
(
itup
,
rel
)
:
0
;
Assert
(
tupnatts
<=
IndexRelationGetNumberOfAttributes
(
rel
));
/*
* We'll execute search using scan key constructed on key columns.
* Truncated attributes and non-key attributes are omitted from the final
* scan key.
*/
key
=
palloc
(
offsetof
(
BTScanInsertData
,
scankeys
)
+
sizeof
(
ScanKeyData
)
*
indnkeyatts
);
if
(
itup
)
_bt_metaversion
(
rel
,
&
key
->
heapkeyspace
,
&
key
->
allequalimage
);
else
{
/* Utility statement callers can set these fields themselves */
key
->
heapkeyspace
=
true
;
key
->
allequalimage
=
false
;
}
key
->
anynullkeys
=
false
;
/* initial assumption */
key
->
nextkey
=
false
;
key
->
pivotsearch
=
false
;
key
->
keysz
=
Min
(
indnkeyatts
,
tupnatts
);
key
->
scantid
=
key
->
heapkeyspace
&&
itup
?
BTreeTupleGetHeapTID
(
itup
)
:
NULL
;
skey
=
key
->
scankeys
;
for
(
i
=
indnkeyatts
;
i
<
tupnatts
;
i
++
)
{
// FmgrInfo *procinfo;
RegProcedure
procedure
;
Datum
arg
;
bool
null
;
int
flags
;
/*
* We can use the cached (default) support procs since no cross-type
* comparison can be needed.
*/
// procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
procedure
=
index_getprocid
(
rel
,
i
+
1
,
BTORDER_PROC
);
/*
* Key arguments built from truncated attributes (or when caller
* provides no tuple) are defensively represented as NULL values. They
* should never be used.
*/
if
(
i
<
tupnatts
)
arg
=
index_getattr
(
itup
,
i
+
1
,
itupdesc
,
&
null
);
else
{
arg
=
(
Datum
)
0
;
null
=
true
;
}
flags
=
(
null
?
SK_ISNULL
:
0
)
|
(
indoption
[
i
]
<<
SK_BT_INDOPTION_SHIFT
);
ScanKeyEntryInitialize
(
&
skey
[
i
],
flags
,
(
AttrNumber
)
(
i
+
1
),
InvalidStrategy
,
InvalidOid
,
rel
->
rd_indcollation
[
i
],
procedure
,
arg
);
/* Record if any key attribute is NULL (or truncated) */
if
(
null
)
key
->
anynullkeys
=
true
;
}
return
key
;
}
/* CS631 End */
This diff is collapsed.
Click to expand it.
src/include/access/nbtree.h
View file @
bddbccd5
...
...
@@ -1231,6 +1231,9 @@ extern bool _bt_first(IndexScanDesc scan, ScanDirection dir);
extern
bool
_bt_next
(
IndexScanDesc
scan
,
ScanDirection
dir
);
extern
Buffer
_bt_get_endpoint
(
Relation
rel
,
uint32
level
,
bool
rightmost
,
Snapshot
snapshot
);
/* CS631 Start */
extern
int32
_bt_compare_fd
(
Relation
rel
,
IndexTuple
itup_
,
BTScanInsert
key
,
Page
page
,
OffsetNumber
offnum
);
/* CS631 Start */
/*
* prototypes for functions in nbtutils.c
...
...
@@ -1266,6 +1269,9 @@ extern bool _bt_check_natts(Relation rel, bool heapkeyspace, Page page,
extern
void
_bt_check_third_page
(
Relation
rel
,
Relation
heap
,
bool
needheaptidspace
,
Page
page
,
IndexTuple
newtup
);
extern
bool
_bt_allequalimage
(
Relation
rel
,
bool
debugmessage
);
/* CS631 Start */
extern
BTScanInsert
_bt_mkscankey_nonkey
(
Relation
rel
,
IndexTuple
itup
);
/* Cs631 End */
/*
* prototypes for functions in nbtvalidate.c
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment