Commit bddbccd5 authored by Abuhujair Javed's avatar Abuhujair Javed

Functional Dependency

parent 9c5cbed9
......@@ -42,3 +42,10 @@ lib*.pc
/Debug/
/Release/
/tmp_install/
.cproject
.project
gmake.out
gmake_install.out
install*
logfile
......@@ -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 -O2"
CFLAGS="-g -O0"
else
CFLAGS="-g"
fi
else
if test "$GCC" = yes; then
CFLAGS="-O2"
CFLAGS="-O0"
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 -O2"
CXXFLAGS="-g -O0"
else
CXXFLAGS="-g"
fi
else
if test "$GXX" = yes; then
CXXFLAGS="-O2"
CXXFLAGS="-O0"
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="-O2"
CFLAGS="-O0"
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="-O2"
CXXFLAGS="-O0"
else
# if the user selected debug mode, don't use -O
if test "$enable_debug" != yes; then
......
......@@ -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 &&
......
......@@ -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 */
......@@ -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 */
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment