Commit 580e0055 authored by Abuhujair Javed's avatar Abuhujair Javed

Final Commit for to implement Functional Dependency in PostgreSQL

parent cd0de49f
...@@ -25,3 +25,14 @@ instructions. ...@@ -25,3 +25,14 @@ instructions.
The latest version of this software may be obtained at The latest version of this software may be obtained at
https://www.postgresql.org/download/. For more information look at our https://www.postgresql.org/download/. For more information look at our
web site located at https://www.postgresql.org/. web site located at https://www.postgresql.org/.
Following Files have been ammended to include functional dependency in PostgreSQL.
src/backend/access/nbtree/nbtinsert.c
src/backend/access/nbtree/nbtsearch.c
src/backend/access/nbtree/nbtutils.c
src/backend/catalog/index.c
src/backend/tcop/postgres.c
src/include/access/nbtree.h
install/data/gdata.h
/* CS631 Start */
/*
* gdata.h
*
* Created on: 28-Nov-2022
* Author: abuhujair
*/
extern int fd_flag;
int check_fd(int id_num);
#ifndef INSTALL_DATA_GDATA_H_
#define INSTALL_DATA_GDATA_H_
#endif /* INSTALL_DATA_GDATA_H_ */
/* CS631 End */
32789
40981
40982
40986
40987
40991
49176
49183
49184
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#include "storage/smgr.h" #include "storage/smgr.h"
/* CS631 Start */ /* CS631 Start */
/* The file at /install/data/gdata.h/
* */
#include "/home/abuhujair/git/postgresql/install/data/gdata.h" #include "/home/abuhujair/git/postgresql/install/data/gdata.h"
/* CS631 End */ /* CS631 End */
...@@ -111,9 +113,10 @@ _bt_doinsert(Relation rel, IndexTuple itup, ...@@ -111,9 +113,10 @@ _bt_doinsert(Relation rel, IndexTuple itup,
bool checkingunique = (checkUnique != UNIQUE_CHECK_NO); bool checkingunique = (checkUnique != UNIQUE_CHECK_NO);
/* CS631 Start */ /* CS631 Start */
// Oid special = 32788; /* We are creating a flag to implement FD functionality.
* FD implementation is being done in line with what postgres implements to do uniqueness check.
* */
bool checkingfd = false; bool checkingfd = false;
// if ( rel->rd_index->indexrelid == special )
if ( check_fd( (int)rel->rd_index->indexrelid ) ) if ( check_fd( (int)rel->rd_index->indexrelid ) )
checkingfd = true; checkingfd = true;
/* CS631 End */ /* CS631 End */
...@@ -212,6 +215,9 @@ search: ...@@ -212,6 +215,9 @@ search:
*/ */
/* CS631 Start */ /* CS631 Start */
/* We will enter the _bt_check_unique function in case
* while checking for FD as well as to check uniqueness.
* */
if (checkingunique || checkingfd) if (checkingunique || checkingfd)
/* CS631 End */ /* CS631 End */
{ {
...@@ -436,9 +442,10 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel, ...@@ -436,9 +442,10 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel,
int curposti = 0; int curposti = 0;
/* CS631 Start */ /* CS631 Start */
// Oid special = 32788; /* We are again checking if the given index defines any FD constraints.
* and raising the flag.
* */
bool checkfd = false; bool checkfd = false;
//if ( rel->rd_index->indexrelid == special )
if ( check_fd((int)rel->rd_index->indexrelid) ) if ( check_fd((int)rel->rd_index->indexrelid) )
checkfd = true; checkfd = true;
/* CS631 End */ /* CS631 End */
...@@ -679,6 +686,8 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel, ...@@ -679,6 +686,8 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel,
insertstate->bounds_valid = false; insertstate->bounds_valid = false;
/* CS631 Start */ /* CS631 Start */
/* depending on whether the checkUnique flag was turned on,
* or checkfd we will decide which error message to be displayed */
if ( checkUnique ) if ( checkUnique )
{ {
Datum values[INDEX_MAX_KEYS]; Datum values[INDEX_MAX_KEYS];
......
...@@ -756,7 +756,14 @@ _bt_compare(Relation rel, ...@@ -756,7 +756,14 @@ _bt_compare(Relation rel,
} }
/* CS631 Start */ /* CS631 Start */
// if (rel->rd_index->indexrelid == special) /* The _bt_compare function implements tiebreaker in case of primary/unique key
* as non-pivot search, which imply it will return the offset the first index tuple
* it matches with, while for non-primary key it returns the offset of one more
* than last tuple which is equal to key.
* For checking FD constraint, we need to verify with first element in the tree.
* So instead of breaking tie using some other factor in case of FD index,
* we return 0, indicating we found a match.
* */
if ( check_fd((int)rel->rd_index->indexrelid) ) if ( check_fd((int)rel->rd_index->indexrelid) )
return 0; return 0;
/* CS631 End */ /* CS631 End */
...@@ -2514,14 +2521,19 @@ _bt_initialize_more_data(BTScanOpaque so, ScanDirection dir) ...@@ -2514,14 +2521,19 @@ _bt_initialize_more_data(BTScanOpaque so, ScanDirection dir)
/* CS631 Start */ /* CS631 Start */
/*---------- /*----------
* _bt_compare_fd() -- Compare insertion-type scankey to tuple on a page. * _bt_compare_fd() -- Compare the inserting tuple with that of tuple in the tree.
* *
* page/offnum: location of btree item to be compared to. * page/offnum: location of btree item to be compared to.
* *
* This routine returns: *
* <0 if scankey < tuple at offnum; * For A->B FD constraints this routine returns:
* 0 if scankey == tuple at offnum; * A B Return Value
* >0 if scankey > tuple at offnum. * Equal Equal 1
* Unequal Equal 1
* Equal Unequal 0
* Unequal Unequal 1
*
* Here A is represented by key of the index, and B is the Covering attribute of the index.
* *
* NULLs in the keys are treated as sortable values. Therefore * NULLs in the keys are treated as sortable values. Therefore
* "equality" does not necessarily mean that the item should be returned * "equality" does not necessarily mean that the item should be returned
...@@ -2550,13 +2562,10 @@ _bt_compare_fd(Relation rel, ...@@ -2550,13 +2562,10 @@ _bt_compare_fd(Relation rel,
TupleDesc itupdesc = RelationGetDescr(rel); TupleDesc itupdesc = RelationGetDescr(rel);
BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page); BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page);
IndexTuple itup; IndexTuple itup;
// ItemPointer heapTid;
ScanKey scankey; ScanKey scankey;
int ncmpkey; int ncmpkey;
int ntupatts; int ntupatts;
int32 result; int32 result;
// BTScanInsert nonkey;
// ScanKey scannonkey;
Assert(_bt_check_natts(rel, key->heapkeyspace, page, offnum)); Assert(_bt_check_natts(rel, key->heapkeyspace, page, offnum));
Assert(key->keysz <= IndexRelationGetNumberOfKeyAttributes(rel)); Assert(key->keysz <= IndexRelationGetNumberOfKeyAttributes(rel));
...@@ -2584,6 +2593,10 @@ _bt_compare_fd(Relation rel, ...@@ -2584,6 +2593,10 @@ _bt_compare_fd(Relation rel,
* _bt_first). * _bt_first).
*/ */
/* Here we are only checking the key attributes of the index,
* which is similar to the one in _bt_compare. Here we have ommitted, tie breakers
* we are just checking for equality.
* */
ncmpkey = Min(ntupatts, key->keysz); ncmpkey = Min(ntupatts, key->keysz);
Assert(key->heapkeyspace || ncmpkey == key->keysz); Assert(key->heapkeyspace || ncmpkey == key->keysz);
Assert(!BTreeTupleIsPosting(itup) || key->allequalimage); Assert(!BTreeTupleIsPosting(itup) || key->allequalimage);
...@@ -2615,8 +2628,12 @@ _bt_compare_fd(Relation rel, ...@@ -2615,8 +2628,12 @@ _bt_compare_fd(Relation rel,
scankey++; scankey++;
} }
// nonkey = _bt_mkscankey_nonkey(rel, itup_); /* This part check for inequality in B and is checked only if A is unequal.
// scannonkey = nonkey->scankeys; * We are essentially comparing all the attributes of covering index
* using the sk_func of the first attribute of A. Hence, this became our
* constraints while implementing FD. All the attributes of B, need to be of same
* datatype as first attribute of A.
* */
scankey = key->scankeys; scankey = key->scankeys;
for (int i = ncmpkey+1; i <= ntupatts; i++) for (int i = ncmpkey+1; i <= ntupatts; i++)
{ {
...@@ -2637,7 +2654,6 @@ _bt_compare_fd(Relation rel, ...@@ -2637,7 +2654,6 @@ _bt_compare_fd(Relation rel,
result = 0; result = 0;
return result; return result;
} }
scankey++;
} }
if (result == 0){ if (result == 0){
...@@ -2647,4 +2663,3 @@ _bt_compare_fd(Relation rel, ...@@ -2647,4 +2663,3 @@ _bt_compare_fd(Relation rel,
} }
/* CS631 End */ /* CS631 End */
...@@ -2752,33 +2752,14 @@ _bt_allequalimage(Relation rel, bool debugmessage) ...@@ -2752,33 +2752,14 @@ _bt_allequalimage(Relation rel, bool debugmessage)
/* CS631 Start */ /* CS631 Start */
/* /*
* _bt_mkscankey * _bt_mkscankey_nonkey
* Build an insertion scan key that contains comparison data from itup * Build a scan key that contains comparison data from itup
* as well as comparator routines appropriate to the key datatypes. * as well as comparator routines appropriate to the 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 * The result is intended for use with _bt_compare_fd(). But did, not workout,
* determine whether or not the keys in the index are expected to be * as index relation data does not store information about comparator routines
* unique (i.e. if this is a "heapkeyspace" index). We assume a * for nonkey attributes. Hence the function is not being used. Other functionality
* heapkeyspace index when caller passes a NULL tuple, allowing index * of the function is similar to the _bt_mkscankey.
* 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 BTScanInsert
_bt_mkscankey_nonkey(Relation rel, IndexTuple itup) _bt_mkscankey_nonkey(Relation rel, IndexTuple itup)
...@@ -2822,7 +2803,6 @@ _bt_mkscankey_nonkey(Relation rel, IndexTuple itup) ...@@ -2822,7 +2803,6 @@ _bt_mkscankey_nonkey(Relation rel, IndexTuple itup)
skey = key->scankeys; skey = key->scankeys;
for (i = indnkeyatts; i < tupnatts; i++) for (i = indnkeyatts; i < tupnatts; i++)
{ {
// FmgrInfo *procinfo;
RegProcedure procedure; RegProcedure procedure;
Datum arg; Datum arg;
bool null; bool null;
...@@ -2832,7 +2812,6 @@ _bt_mkscankey_nonkey(Relation rel, IndexTuple itup) ...@@ -2832,7 +2812,6 @@ _bt_mkscankey_nonkey(Relation rel, IndexTuple itup)
* We can use the cached (default) support procs since no cross-type * We can use the cached (default) support procs since no cross-type
* comparison can be needed. * comparison can be needed.
*/ */
// procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
procedure = index_getprocid(rel, i + 1, BTORDER_PROC); procedure = index_getprocid(rel, i + 1, BTORDER_PROC);
......
...@@ -86,13 +86,11 @@ ...@@ -86,13 +86,11 @@
#include "utils/tuplesort.h" #include "utils/tuplesort.h"
/* CS631 Start */ /* CS631 Start */
# include <string.h> #include <string.h>
# include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <limits.h> #include <limits.h>
// #include "../../../install/data/gdata.h"
#include "/home/abuhujair/git/postgresql/install/data/gdata.h" #include "/home/abuhujair/git/postgresql/install/data/gdata.h"
/* CS631 End */ /* CS631 End */
...@@ -537,6 +535,9 @@ AppendAttributeTuples(Relation indexRelation, Datum *attopts) ...@@ -537,6 +535,9 @@ AppendAttributeTuples(Relation indexRelation, Datum *attopts)
} }
/* CS631 Start */ /* CS631 Start */
/* This function adds an entry of relation id of the index to the file inx_inf.txt if
* user wants to implements index as an FD
* */
int add_entry(char *idxid) int add_entry(char *idxid)
{ {
...@@ -682,6 +683,8 @@ UpdateIndexRelation(Oid indexoid, ...@@ -682,6 +683,8 @@ UpdateIndexRelation(Oid indexoid,
heap_freetuple(tuple); heap_freetuple(tuple);
/* CS631 Start */ /* CS631 Start */
/* If the given index is created successfully, and if the index is created
* to implement FD constraints we will add it.*/
if(fd_flag) if(fd_flag)
{ {
char idxid[20]; char idxid[20];
......
...@@ -946,6 +946,9 @@ pg_plan_queries(List *querytrees, const char *query_string, int cursorOptions, ...@@ -946,6 +946,9 @@ pg_plan_queries(List *querytrees, const char *query_string, int cursorOptions,
} }
/* CS631 Start */ /* CS631 Start */
/* We have not ammended the parser to parse the SQL query to create FD, instead
* just changing the "FD" to "INDEX" and "determines" to "include" we are creating FD.
* */
char* replaceWord(const char* s, const char* oldW, char* replaceWord(const char* s, const char* oldW,
const char* newW) const char* newW)
{ {
...@@ -974,8 +977,14 @@ char* replaceWord(const char* s, const char* oldW, ...@@ -974,8 +977,14 @@ char* replaceWord(const char* s, const char* oldW,
} }
#include "../../../install/data/gdata.h" #include "../../../install/data/gdata.h"
/* This flag is being used to indicate whether the query is create FD.*/
int fd_flag=0; int fd_flag=0;
/* This function is being called whenver we want to check if the given index relation
* ID is an FD.
* Since we have saved the index which implements the FD constraints in file, this just
* searches the index in the file.
* */
int check_fd(int id_num) int check_fd(int id_num)
{ {
FILE * fp; FILE * fp;
...@@ -1014,6 +1023,8 @@ exec_simple_query(const char *query_string) ...@@ -1014,6 +1023,8 @@ exec_simple_query(const char *query_string)
char msec_str[32]; char msec_str[32];
/* CS631 Start */ /* CS631 Start */
/* If the given SQL query is to create FD, this will create and equivalent query to create the index
* and raise the fd_flag*/
fd_flag=0; fd_flag=0;
if (strstr(query_string, "FD") && strstr(query_string, "determines")) { if (strstr(query_string, "FD") && strstr(query_string, "determines")) {
const char old[]="FD"; const char old[]="FD";
......
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