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
Nov 28, 2022
by
Abuhujair Javed
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Functional Dependency
parent
9c5cbed9
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
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
...
...
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
&&
...
...
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 */
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 */
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
...
...
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