├── .gitignore ├── README.md ├── Reports ├── biblio.bib ├── chngcntr.sty ├── compile_report.sh ├── final_presentation.tex ├── final_report.tex ├── kbordermatrix.sty ├── pics │ ├── 100.svg │ ├── 1000.svg │ ├── 10000.svg │ ├── 90000.svg │ ├── foreign_key.svg │ ├── graph.png │ ├── model.svg │ ├── nitk_logo.jpg │ ├── primary_key.svg │ ├── time.svg │ └── trie.svg └── tikz-er2.sty └── src ├── database.h ├── domain.h ├── main.cpp ├── nodes.h ├── select.h ├── table.h ├── test.h ├── test_scripts └── insert.php └── trie.h /.gitignore: -------------------------------------------------------------------------------- 1 | src/a.out 2 | src/test 3 | src/test.txt 4 | src/main 5 | src/main.exe 6 | src/test_files/* 7 | *.pdf 8 | Reports/*.aux 9 | Reports/*.bbl 10 | Reports/*.blg 11 | Reports/*.lof 12 | Reports/*.log 13 | Reports/*.lot 14 | Reports/*.out 15 | Reports/*.toc 16 | Reports/*.snm 17 | Reports/*.nav 18 | Reports/*.tex.backup 19 | theory/* 20 | results/* 21 | *~ 22 | *.o 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Relational-Graph-Database 2 | Graph based storage of Relational Database 3 | -------------------------------------------------------------------------------- /Reports/biblio.bib: -------------------------------------------------------------------------------- 1 | @article{graph_database_survey, 2 | author = {Angles, Renzo and Gutierrez, Claudio}, 3 | title = {Survey of Graph Database Models}, 4 | journal = {ACM Comput. Surv.}, 5 | issue_date = {February 2008}, 6 | volume = {40}, 7 | number = {1}, 8 | month = feb, 9 | year = {2008}, 10 | issn = {0360-0300}, 11 | pages = {1:1--1:39}, 12 | articleno = {1}, 13 | numpages = {39}, 14 | url = {http://doi.acm.org/10.1145/1322432.1322433}, 15 | doi = {10.1145/1322432.1322433}, 16 | acmid = {1322433}, 17 | publisher = {ACM}, 18 | address = {New York, NY, USA}, 19 | keywords = {Database systems, database models, graph database models, graph databases, graph integrity constraints, graph query languages}, 20 | } 21 | 22 | @inproceedings{load_balancing, 23 | author = {Khayyat, Zuhair and Awara, Karim and Alonazi, Amani and Jamjoom, Hani and Williams, Dan and Kalnis, Panos}, 24 | title = {Mizan: A System for Dynamic Load Balancing in Large-scale Graph Processing}, 25 | booktitle = {Proceedings of the 8th ACM European Conference on Computer Systems}, 26 | series = {EuroSys '13}, 27 | year = {2013}, 28 | isbn = {978-1-4503-1994-2}, 29 | location = {Prague, Czech Republic}, 30 | pages = {169--182}, 31 | numpages = {14}, 32 | url = {http://doi.acm.org/10.1145/2465351.2465369}, 33 | doi = {10.1145/2465351.2465369}, 34 | acmid = {2465369}, 35 | publisher = {ACM}, 36 | address = {New York, NY, USA}, 37 | } 38 | 39 | 40 | @article{neo4j, 41 | title={Neo4J}, 42 | author={Developers, Neo4J}, 43 | journal={Graph NoSQL Database $\{$online$\}$}, 44 | year={2012} 45 | } 46 | 47 | @inproceedings{titan, 48 | title={Titan: a high-performance remote-sensing database}, 49 | author={Chang, Chialin and Moon, Bongki and Acharya, Anurag and Shock, Carter and Sussman, Alan and Saltz, Joel}, 50 | booktitle={Data Engineering, 1997. Proceedings. 13th International Conference on}, 51 | pages={375--384}, 52 | year={1997}, 53 | organization={IEEE} 54 | } 55 | 56 | @article{orientdb, 57 | title={OrientDB}, 58 | author={Developers, OrientDB}, 59 | journal={Hybrid Document-Store and Graph NoSQL Database $\{$online$\}$}, 60 | year={2012} 61 | } 62 | 63 | @inproceedings{graph_relational_comparison, 64 | author = {Vicknair, Chad and Macias, Michael and Zhao, Zhendong and Nan, Xiaofei and Chen, Yixin and Wilkins, Dawn}, 65 | title = {A Comparison of a Graph Database and a Relational Database: A Data Provenance Perspective}, 66 | booktitle = {Proceedings of the 48th Annual Southeast Regional Conference}, 67 | series = {ACM SE '10}, 68 | year = {2010}, 69 | isbn = {978-1-4503-0064-3}, 70 | location = {Oxford, Mississippi}, 71 | pages = {42:1--42:6}, 72 | articleno = {42}, 73 | numpages = {6}, 74 | url = {http://doi.acm.org/10.1145/1900008.1900067}, 75 | doi = {10.1145/1900008.1900067}, 76 | acmid = {1900067}, 77 | publisher = {ACM}, 78 | address = {New York, NY, USA}, 79 | } 80 | 81 | @article{redundancy, 82 | author = {Codd, E. F.}, 83 | title = {A Relational Model of Data for Large Shared Data Banks}, 84 | journal = {Commun. ACM}, 85 | issue_date = {Jan. 1983}, 86 | volume = {26}, 87 | number = {1}, 88 | month = jan, 89 | year = {1983}, 90 | issn = {0001-0782}, 91 | pages = {64--69}, 92 | numpages = {6}, 93 | url = {http://doi.acm.org/10.1145/357980.358007}, 94 | doi = {10.1145/357980.358007}, 95 | acmid = {358007}, 96 | publisher = {ACM}, 97 | address = {New York, NY, USA}, 98 | keywords = {composition, consistency, data bank, data base, data integrity, data organization, data structure, derivability, hierarchies of data, join, networks of data, predicate calculus, redundancy, relations, retrieval language, security}, 99 | } 100 | 101 | @ARTICLE{object_graph, 102 | author={Gyssens, M. and Paredaens, J. and Van den Bussche, J. and Van Gucht, D.}, 103 | journal={Knowledge and Data Engineering, IEEE Transactions on}, 104 | title={A graph-oriented object database model}, 105 | year={1994}, 106 | month={Aug}, 107 | volume={6}, 108 | number={4}, 109 | pages={572-586}, 110 | keywords={data structures;database management systems;object-oriented databases;query languages;spatial data structures;user interfaces;DAPLEX;GOOD;conceptual representation;data manipulation;database models;expressiveness;graph transformations;graph-oriented object database model;natural semantics;object-oriented databases;object-oriented modeling;pattern matching;query languages;user interfaces;Application software;Computer science;Data models;Database languages;Database systems;Object oriented databases;Object oriented modeling;Pattern matching;Power system modeling;Relational databases}, 111 | doi={10.1109/69.298174}, 112 | ISSN={1041-4347},} 113 | 114 | @INPROCEEDINGS{indexing, 115 | author={Williams, D.W. and Jun Huan and Wei Wang}, 116 | booktitle={Data Engineering, 2007. ICDE 2007. IEEE 23rd International Conference on}, 117 | title={Graph Database Indexing Using Structured Graph Decomposition}, 118 | year={2007}, 119 | month={April}, 120 | pages={976-985}, 121 | keywords={data structures;database indexing;directed graphs;query processing;table lookup;adjacency matrices;code-based canonical representation;database graphs;directed acyclic graph;fast isomorphic lookup;graph database indexing;hash tables;similarity queries;structured graph decomposition;subgraph isomorphism queries;Chemicals;Computer science;Data engineering;Databases;Drugs;Indexing;Pattern matching;Proteins;Testing;Tree graphs}, 122 | doi={10.1109/ICDE.2007.368956},} 123 | -------------------------------------------------------------------------------- /Reports/chngcntr.sty: -------------------------------------------------------------------------------- 1 | % chngcntr.sty 2 | % 3 | % Provides commands to change the resetting of counters. 4 | % Instructions for use are at the end of this file. 5 | % 6 | % Author: Peter Wilson, Herries Press 7 | % Maintainer: Will Robertson (will dot robertson at latex-project dot org) 8 | % Released under the Latex Project Public License 9 | % 10 | % 11 | \NeedsTeXFormat{LaTeX2e} 12 | \ProvidesPackage{chngcntr}[2009/09/02 v1.0a change counter resetting] 13 | % 14 | % This package uses David Carlisle's \@removefromreset command as 15 | % specified in the remreset package available from CTAN as 16 | % macros/latex/contrib/supported/carlisle/remreset.sty 17 | % It is \provided here as a convenience to the user, and with 18 | % David Carlisle's permission. 19 | % START OF DAVID CARLISLE'S CODE 20 | \providecommand{\@removefromreset}[2]{{% 21 | \expandafter\let\csname c@#1\endcsname\@removefromreset 22 | \def\@elt##1{% 23 | \expandafter\ifx\csname c@##1\endcsname\@removefromreset 24 | \else 25 | \noexpand\@elt{##1}% 26 | \fi}% 27 | \expandafter\xdef\csname cl@#2\endcsname{% 28 | \csname cl@#2\endcsname}}} 29 | % END OF DAVID CARLISLE'S CODE 30 | 31 | %%\@ifbothc@t@s{}{}{}{} 32 | \newcommand{\@ifbothc@t@s}[4]{% 33 | \@ifundefined{c@#2}{% counter undefined 34 | \PackageError{#1}{#2 is not a counter}{\@eha}}% 35 | {% else counter is defined 36 | \@ifundefined{c@#3}{% within undefined 37 | \PackageError{#1}{#3 is not a counter}{\@eha}}% 38 | {% else both counter and within are defined 39 | #4}}} 40 | 41 | %%\counterwithout*{}{} 42 | \newcommand{\counterwithout}{\@ifstar{\c@t@soutstar}{\c@t@sout}} 43 | \newcommand{\c@t@soutstar}[2]{% 44 | \@ifbothc@t@s{chngcntr}{#1}{#2}{\@removefromreset{#1}{#2}}} 45 | \newcommand{\c@t@sout}[2]{% 46 | \@ifbothc@t@s{chngcntr}{#1}{#2}{\@removefromreset{#1}{#2}% 47 | \@namedef{the#1}{\arabic{#1}}}} 48 | 49 | 50 | %%\counterwithin*{}{} 51 | \newcommand{\counterwithin}{\@ifstar{\c@t@sinstar}{\c@t@sin}} 52 | \newcommand{\c@t@sinstar}[2]{% 53 | \@ifbothc@t@s{chngcntr}{#1}{#2}{\@addtoreset{#1}{#2}}} 54 | \newcommand{\c@t@sin}[2]{% 55 | \@ifbothc@t@s{chngcntr}{#1}{#2}{\@addtoreset{#1}{#2}% 56 | \@namedef{the#1}{\@nameuse{the#2}.\arabic{#1}}}} 57 | 58 | 59 | \endinput 60 | 61 | %%%%%%%%%%%%%%%%%% 62 | % USAGE 63 | %%%%%%%%%%%%%%%%%% 64 | % 65 | % In LaTeX, a new counter called, say `ctr', is created by the command 66 | % \newcounter{ctr}[within]. If the optional within argument is given 67 | % the the counter `ctr' is reset to zero each time the counter `within' 68 | % changes. The command \thectr typesets the value of the counter ctr. 69 | % This is automatically defined by \newcounter and is initialised 70 | % to typeset arabic numerals. 71 | % 72 | %%%%%%%%%%%%%%%%% 73 | % \counterwithin 74 | % \counterwithin* 75 | %%%%%%%%%%%%%%%%% 76 | % It is sometimes desireable to change a counter that has been defined 77 | % by \newcounter{ctr} to act as though it had been defined as 78 | % \newcounter{ctr}[within]. The package provides the command 79 | % \counterwithin{ctr}{within} that accomplishes this. By default, 80 | % it also redefines the \thectr command so that it typesets values 81 | % in the style \thewithin.\arabic{ctr}. The starred version of the 82 | % command suppresses the redefinition of \thectr 83 | % (e.g., \counterwithin*{ctr}{within}). 84 | % 85 | %%%%%%%%%%%%%%%%%% 86 | % \counterwithout 87 | % \counterwithout* 88 | %%%%%%%%%%%%%%%%%% 89 | % Likewise, the command \counterwithout{ctr}{within} changes a 90 | % counter that has been created by \newcounter{ctr}[within] to act 91 | % as though it had been created by \newcounter{ctr}. By default it 92 | % also redefines the \thectr command so that it just typesets an arabic 93 | % numeral. The starred version of the command suppresses the redefinition 94 | % of \thectr. 95 | % 96 | % Any number of \counterwithin{ctr}{...} and \counterwithout{ctr}{...} 97 | % commands can be issued for a given counter, ctr, if you wish to toggle 98 | % between the two styles. The current value of ctr is unaffected by 99 | % \counterwithin and \counterwithout. If you want to change the value 100 | % after one of these commands, use \setcounter{ctr}{...}, and to change 101 | % the typeseting style use \renewcommand{\thectr}{...}. 102 | % 103 | % 104 | % Peter W. 105 | % 2001/03/30 106 | % 107 | % Change History: 108 | % v1.0a - New maintainer (Will Robertson) 109 | % 110 | 111 | -------------------------------------------------------------------------------- /Reports/compile_report.sh: -------------------------------------------------------------------------------- 1 | #!bin/bash 2 | 3 | #Depends on Inkscape and PDFLatex 4 | 5 | #Converting Images to Pdf 6 | if hash inkscape > /dev/null 2>&1; 7 | then 8 | #using inkscape 9 | 10 | inkscape -D -z --file=pics/foreign_key.svg --export-pdf=pics/foreign_key.pdf 11 | 12 | inkscape -D -z --file=pics/model.svg --export-pdf=pics/model.pdf 13 | 14 | inkscape -D -z --file=pics/primary_key.svg --export-pdf=pics/primary_key.pdf 15 | 16 | inkscape -D -z --file=pics/trie.svg --export-pdf=pics/trie.pdf 17 | 18 | inkscape -D -z --file=pics/100.svg --export-pdf=pics/100.pdf 19 | 20 | inkscape -D -z --file=pics/1000.svg --export-pdf=pics/1000.pdf 21 | 22 | inkscape -D -z --file=pics/10000.svg --export-pdf=pics/10000.pdf 23 | 24 | inkscape -D -z --file=pics/90000.svg --export-pdf=pics/90000.pdf 25 | 26 | inkscape -D -z --file=pics/time.svg --export-pdf=pics/time.pdf 27 | 28 | else 29 | if ! hash rsvg-convert > /dev/null 2>&1; 30 | then 31 | #Install Requird Library 32 | apt-get install librsvg2-bin 33 | fi 34 | #Use rsvg 35 | 36 | rsvg-convert -f pdf -o pics/model.pdf pics/model.svg 37 | 38 | rsvg-convert -f pdf -o pics/foreign_key.pdf pics/foreign_key.svg 39 | 40 | rsvg-convert -f pdf -o pics/primary_key.pdf pics/primary_key.svg 41 | 42 | rsvg-convert -f pdf -o pics/trie.pdf pics/trie.svg 43 | 44 | rsvg-convert -f pdf -o pics/100.pdf pics/100.svg 45 | 46 | rsvg-convert -f pdf -o pics/1000.pdf pics/1000.svg 47 | 48 | rsvg-convert -f pdf -o pics/10000.pdf pics/10000.svg 49 | 50 | rsvg-convert -f pdf -o pics/90000.pdf pics/90000.svg 51 | 52 | rsvg-convert -f pdf -o pics/time.pdf pics/time.svg 53 | 54 | fi 55 | 56 | #Compiling Latex which includes pdfs 57 | if ! hash pdflatex > /dev/null 2>&1; 58 | then 59 | apt-get install pdflatex 60 | fi 61 | 62 | pdflatex final_report.tex 63 | pdflatex final_presentation.tex 64 | 65 | #Cleaning up junk files generated 66 | rm *.aux 67 | rm *.lof 68 | rm *.log 69 | rm *.lot 70 | rm *.out 71 | rm *.tex.backup 72 | rm *.toc 73 | rm *.nav 74 | rm *.snm 75 | -------------------------------------------------------------------------------- /Reports/final_presentation.tex: -------------------------------------------------------------------------------- 1 | \documentclass[14pt,xcolor=dvipsnames, aspectratio=169]{beamer} 2 | \usetheme{AnnArbor} 3 | \usecolortheme{crane} 4 | 5 | \usepackage{hyperref} 6 | \usepackage{url} 7 | \hypersetup{urlcolor=red} 8 | 9 | \renewcommand{\bibname}{References} 10 | \setbeamertemplate{bibliography item}{[\theenumiv]} 11 | 12 | \usepackage{kbordermatrix} 13 | \usepackage{multicol} 14 | \usepackage{verbatim} 15 | \usepackage{graphics} 16 | \usepackage{graphicx} 17 | \usepackage{tikz} 18 | 19 | 20 | %Basic Information 21 | \title{Graph Based Storage for Relational Database} 22 | \author{Adarsh, Ajith, Ashish, Sourabh} 23 | \date{\today} 24 | 25 | %-------------------------------------------------------------------------------------- 26 | % TITLE PAGE (Slide 1) 27 | %-------------------------------------------------------------------------------------- 28 | \begin{document} 29 | \begin{frame} 30 | \titlepage 31 | \end{frame} 32 | %-------------------------------------------------------------------------------------- 33 | 34 | 35 | %-------------------------------------------------------------------------------------- 36 | % Outline 37 | %-------------------------------------------------------------------------------------- 38 | \begin{frame} 39 | \frametitle{Outline} 40 | \begin{multicols}{2} 41 | \tableofcontents[hideallsubsections] 42 | \end{multicols} 43 | \end{frame} 44 | 45 | \section{Introduction} 46 | \begin{frame} 47 | \frametitle{Introduction} 48 | \begin{itemize} 49 | \item Problem Description 50 | \begin{itemize} 51 | \item Data redundancy 52 | \item Join query 53 | \end{itemize} 54 | \end{itemize} 55 | \end{frame} 56 | 57 | \section{Problem Statement} 58 | \begin{frame} 59 | \frametitle{Problem Statement} 60 | \begin{itemize} 61 | \item To develop a data storage system based on graph structure in order to optimize the query execution time especially join queries and eliminate some sort of data redundancy in a relational model while retaining other advantages of relational database system in terms of performance of other queries. 62 | \end{itemize} 63 | \end{frame} 64 | 65 | \section{Objectives} 66 | \begin{frame} 67 | \frametitle{Objectives} 68 | \begin{itemize} 69 | \item<1-> To explore the pros and cons of the graph model. 70 | \item<2-> To compare the relational model with the graph model. 71 | \item<3-> To develop a model which can represent relational database. 72 | \item<4-> To define relational algebraic operations on the model such that it has most of the advantages of both the models. 73 | \item<5-> To understand the differences of the proposed model with the graph model. 74 | \item<6-> To realize the limitations of the proposed model. 75 | \end{itemize} 76 | \end{frame} 77 | 78 | \section{Overview of Model} 79 | \begin{frame} 80 | \frametitle{Overview of the Model} 81 | \begin{itemize} 82 | \item<1-> A database consist of multiple tables 83 | \item<2-> Each table is a collection of domains 84 | \item<3-> Each table contains list of main node records 85 | \end{itemize} 86 | \end{frame} 87 | 88 | \begin{frame} 89 | \begin{figure}[t] 90 | \centering 91 | \includegraphics[width=0.5\textwidth]{pics/model.pdf} 92 | \caption{Overview of Proposed Graph Based Storage} 93 | \label{fig:overview} 94 | \end{figure} 95 | \end{frame} 96 | 97 | \begin{frame} 98 | \frametitle{Overview of the Model} 99 | \begin{itemize} 100 | \item<1-> A database consist of multiple tables 101 | \item<1-> Each table is a collection of domains 102 | \item<1-> Each table contains list of main node records 103 | \item<2-> Each Domain is collection of attribute nodes 104 | \item<3-> Each attribute node contains the actual data elements 105 | \end{itemize} 106 | \end{frame} 107 | 108 | \section{Handling Constraints} 109 | \begin{frame} 110 | \frametitle{Handling Constraints} 111 | \begin{itemize} 112 | \item Primary Key 113 | \end{itemize} 114 | \end{frame} 115 | 116 | \begin{frame} 117 | \frametitle{Primary Key} 118 | \begin{figure} 119 | \centering 120 | \includegraphics[width=0.5\textwidth]{pics/primary_key.pdf} 121 | \caption{Primary Keys in Proposed Model} 122 | \label{fig:primary_key} 123 | \end{figure} 124 | \end{frame} 125 | 126 | \begin{frame} 127 | \frametitle{Handling Constraints} 128 | \begin{itemize} 129 | \item Primary Key 130 | \item Foreign Key 131 | \end{itemize} 132 | \end{frame} 133 | 134 | \begin{frame} 135 | \frametitle{Foreign Key} 136 | \begin{figure}[h] 137 | \centering 138 | \includegraphics[width=0.32\textwidth]{pics/foreign_key.pdf} 139 | \end{figure} 140 | \end{frame} 141 | 142 | \begin{frame} 143 | \frametitle{Handling Constraints} 144 | \begin{itemize} 145 | \item Primary Key 146 | \item Foreign Key 147 | \item Other Foreign Key Models 148 | \begin{itemize} 149 | \item<2-> Direct Connection Model 150 | \item<3-> Shared Domain Model 151 | \item<4-> Duplicate Domain Model 152 | \end{itemize} 153 | \end{itemize} 154 | \end{frame} 155 | 156 | \section{Indexing} 157 | \begin{frame} 158 | \frametitle{Indexing Using Trie} 159 | \begin{figure} 160 | \centering 161 | \includegraphics[width=0.4\textwidth]{pics/trie.pdf} 162 | \caption{Trie Data Structure for Indexing} 163 | \end{figure} 164 | \end{frame} 165 | 166 | \section{Query Handling} 167 | \begin{frame} 168 | \frametitle{Insert Query} 169 | \begin{itemize} 170 | \item<1-> Check for constraints (Primary and Foreign Key) 171 | \item<2-> Find or Create attribute nodes with given value 172 | \item<3-> Create main node and add to main list 173 | \item<4-> Connect main node with attribute nodes 174 | \end{itemize} 175 | \end{frame} 176 | 177 | \begin{frame} 178 | \frametitle{Select Query} 179 | \begin{itemize} 180 | \item<1-> Find attribute nodes satisfying given propositional formula 181 | \item<2-> Get list of corresponding main nodes 182 | \item<3-> Perform Union or Intersection as required 183 | \item<4-> Project on the resultant set of records 184 | \item<5-> Print the result 185 | \end{itemize} 186 | \end{frame} 187 | 188 | \begin{frame} 189 | \frametitle{Update and Delete Query} 190 | \begin{itemize} 191 | \item<1-> Select records according to given conditions 192 | \item<2-> Find corresponding attribute nodes 193 | \item<3-> Create or find attribute nodes with the updated values if required 194 | \item<4-> Connect or disconnect main node with attribute nodes if required 195 | \item<5-> Mark main node for soft delete if required 196 | \end{itemize} 197 | \end{frame} 198 | 199 | \begin{frame} 200 | \frametitle{Join Query} 201 | \begin{itemize} 202 | \item<1-> Select records in parent relation satisfying propositional formula 203 | \item<2-> Get list of main nodes in child relation corresponding to filtered parent records 204 | \item<3-> Select records in child relation satisfying propositional formula 205 | \item<4-> Perform intersection or union as required 206 | \item<5-> Project on the resultant set of records 207 | \item<6-> Print the result 208 | \end{itemize} 209 | \end{frame} 210 | 211 | \section{Results \& Analysis} 212 | \begin{frame} 213 | \frametitle{Results \& Analysis} 214 | \begin{itemize} 215 | \item Size Measurement 216 | \end{itemize} 217 | \end{frame} 218 | 219 | \begin{frame} 220 | \frametitle{Size Measurement} 221 | \begin{figure} 222 | \centering 223 | \includegraphics[width=0.55\textwidth]{pics/100.pdf} 224 | \end{figure} 225 | \end{frame} 226 | 227 | \begin{frame} 228 | \frametitle{Results \& Analysis} 229 | \begin{itemize} 230 | \item Size Measurement 231 | \item Time Measurement 232 | \end{itemize} 233 | \end{frame} 234 | 235 | \begin{frame} 236 | \frametitle{Time Measurement} 237 | \begin{figure} 238 | \centering 239 | \includegraphics[width=0.55\textwidth]{pics/time.pdf} 240 | \end{figure} 241 | \end{frame} 242 | 243 | \begin{frame} 244 | \frametitle{Future Work} 245 | \begin{itemize} 246 | \item<1-> Parallel Queries 247 | \item<2-> Hybrid Adapting Data Models 248 | \item<3-> Persistent Storage 249 | \item<4-> Query Optimizer 250 | \item<5-> Custom Indexing 251 | \end{itemize} 252 | 253 | \end{frame} 254 | 255 | 256 | \begin{frame} 257 | \frametitle{Thank You} 258 | \huge 259 | \centering 260 | \vspace{1cm} 261 | Thank You ! \\ 262 | \vspace{1.5cm} 263 | \flushright 264 | \flushbottom 265 | \small 266 | Adarsh Mohata - 12IT03 \\ 267 | Ajith P S - 12IT04\\ 268 | Ashish Kedia - 12IT14 \\ 269 | Sourabh Suman - 12IT82 \\ 270 | \end{frame} 271 | 272 | \end{document} -------------------------------------------------------------------------------- /Reports/kbordermatrix.sty: -------------------------------------------------------------------------------- 1 | \NeedsTeXFormat{LaTeX2e} 2 | \ProvidesPackage{kbordermatrix}[2011/09/21 Bordered matrix with brackets] 3 | 4 | % Author: Kim C Border 5 | % Date: SuperBowl XXXVII (Go Bucs) 6 | 7 | % Revised 2003/09/20 8 | % to allow flush right option. 9 | % Revised 2011/09/21 10 | % at urging of Bruno Calfa (CMU) 11 | % to coexist with package arydshln 12 | % by adding \def\@xarraycr ... 13 | 14 | % Defines \kbordermatrix along the lines of plain tex's 15 | % \bordermatrix (which is still available in LaTeX). 16 | 17 | % In particular, as with \bordermatrix, 18 | % 1. It takes the array as an argument. It does not use \begin{}..\end{}. 19 | % Is this a feature or a bug? 20 | % 2. The first row is spaced a bit further apart from the rest. 21 | % 3. The lower (n-1) by (n-1) block is set off by delimiters. 22 | % 4. There is an invisible bottom row of the same height as the segregated 23 | % top row that adds to the height of the equation. 24 | 25 | % Differences from \bordermatrix: 26 | % 1. Square brackets are used in place of parentheses. 27 | % 2. You may use \\ instead of \cr. 28 | % 3. The line heights agree with LaTeX's line heights for the 29 | % array environment, and \arraystretch is respected. This means 30 | % the bottom (n-1) rows align with the rows of an (n-1)-rowed 31 | % \begin{array}..\end{array} (with or without delimiters). 32 | % 4. All columns are centered. 33 | % ** Modified 2003-9-20 to allow flush right option. 34 | % 5. The first column is spaced a bit further apart from the rest. 35 | 36 | 37 | % Differences from \left\[\begin{array}...\end{array}\right\] 38 | % 1. It takes the array as an argument. It does not use \begin{}..\end{}. 39 | % Is this a feature or a bug? 40 | % 2. Consequently, you cannot use a column specifier (e.g., {l|cr}). 41 | % 3. Consequently the maximum number of columns is not specified. 42 | % 4. Vertical rules must be put in each row in a separate column. 43 | % 5. You can use \hline and \cline. 44 | 45 | % At least it works in the cases I have tried, but I offer no guarantees. 46 | 47 | 48 | 49 | % cf. \bordermatrix p. 361, and \vrulealign p. 392 of The TeXbook 50 | 51 | 52 | 53 | % Style parameters, they may be redefined according to taste. 54 | \newcommand{\kbldelim}{[} % Left delimiter 55 | \newcommand{\kbrdelim}{]}% Right delimiter 56 | 57 | \newcommand{\kbrowstyle}{\scriptstyle}% Style applied to first row 58 | \newcommand{\kbcolstyle}{\scriptstyle}% Style applied to first column 59 | 60 | \newlength{\kbcolsep} % Extra separation after first border column 61 | \newlength{\kbrowsep} % Extra separation after first border row 62 | 63 | \setlength{\kbcolsep}{.5\arraycolsep} 64 | \setlength{\kbrowsep}{.2ex} 65 | 66 | \newif\ifkbalignright 67 | 68 | % Scratch lengths (to be computed) 69 | \newlength{\br@kwd} % Width of delimiter 70 | \newlength{\k@bordht} % Height of border column 71 | 72 | % This is it 73 | \newcommand{\kbordermatrix}[1]{% 74 | \begingroup 75 | % \br@kwd depends on font size, so compute it now. 76 | \setbox0=\hbox{$\left\kbldelim\right.$} 77 | \setlength{\br@kwd}{\wd0} 78 | % Compute the array strut based on current value of \arraystretch. 79 | \setbox\@arstrutbox\hbox{\vrule 80 | \@height\arraystretch\ht\strutbox 81 | \@depth\arraystretch\dp\strutbox 82 | \@width\z@} 83 | % Compute height of first row and extra space. 84 | \setlength{\k@bordht}{\kbrowsep} 85 | \addtolength{\k@bordht}{\ht\@arstrutbox} 86 | \addtolength{\k@bordht}{\dp\@arstrutbox} 87 | % turn off mathsurround 88 | \m@th 89 | % Set the first row style 90 | \def\@kbrowstyle{\kbrowstyle} 91 | % Swallow the alignment into box0: 92 | \setbox0=\vbox{% 93 | % Define \cr for first row to include the \kbrowsep 94 | % and to reset the row style 95 | \def\cr{\crcr\noalign{\kern\kbrowsep 96 | \global\let\cr=\endline 97 | \global\let\@kbrowstyle=\relax}} 98 | % Redefine \\ a la LaTeX: 99 | \let\\\@arraycr 100 | % The following are needed to make a solid \vrule with no gaps 101 | % between the lines. 102 | \lineskip\z@skip 103 | \baselineskip\z@skip 104 | % Compute the length of the skip after the first column 105 | \dimen0\kbcolsep \advance\dimen0\br@kwd 106 | % Here begins the alignment: 107 | \ialign{\tabskip\dimen0 % This space will show up after the first column 108 | \kern\arraycolsep\hfil\@arstrut$\kbcolstyle ##$\hfil\kern\arraycolsep& 109 | \tabskip\z@skip % Cancel extra space for other columns 110 | \kern\arraycolsep\hfil$\@kbrowstyle ##$\ifkbalignright\relax\else\hfil\fi\kern\arraycolsep&& 111 | \kern\arraycolsep\hfil$\@kbrowstyle ##$\ifkbalignright\relax\else\hfil\fi\kern\arraycolsep\crcr 112 | % That ends the template. 113 | % Here is the argument: 114 | #1\crcr}% End \ialign 115 | }% End \setbox0. 116 | % \box0 now holds the array. 117 | % 118 | % This next line uses \box2 to hold a throwaway 119 | % copy of \box0, leaving \box0 intact, 120 | % while putting the last row in \box5. 121 | \setbox2=\vbox{\unvcopy0 \global\setbox5=\lastbox} 122 | % We want the width of the first column, 123 | % so we lop off columns until there is only one left. 124 | % It's not elegant or efficient, but at 1 gHz, who cares. 125 | \loop 126 | \setbox2=\hbox{\unhbox5 \unskip \global\setbox3=\lastbox} 127 | \ifhbox3 128 | \global\setbox5=\box2 129 | \global\setbox1=\box3 130 | \repeat 131 | % \box1 now holds the first column of last row. 132 | % 133 | % This next line stores the alignment in \box2, 134 | % while calculating the proper 135 | % delimiter height and placement. 136 | \setbox2=\hbox{$\kern\wd1\kern\kbcolsep\kern-\arraycolsep 137 | \left\kbldelim 138 | \kern-\wd1\kern-\kbcolsep\kern-\br@kwd 139 | % 140 | % Here is the output. The \vcenter aligns the array with the "math axis." 141 | % The negative vertical \kern only shrinks the delimiter's height. 142 | % BTW, I didn't find this in the TeXbook, 143 | % I had to try various \kerns to see what they did in a 144 | % \left[\vcenter{}\right]. 145 | \vcenter{\kern-\k@bordht\vbox{\unvbox0}} 146 | \right\kbrdelim$} 147 | \null\vbox{\kern\k@bordht\box2} 148 | % 149 | \endgroup 150 | } -------------------------------------------------------------------------------- /Reports/pics/100.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 31 | 51 | Gnuplot 53 | Produced by GNUPLOT 4.6 patchlevel 4 55 | 57 | 64 | 66 | 70 | 75 | 80 | 85 | 93 | 102 | 109 | 114 | 119 | 124 | 129 | 134 | 139 | 144 | 145 | 148 | 151 | 155 | 159 | 0 161 | 162 | 166 | 170 | 2000 172 | 173 | 177 | 181 | 4000 183 | 184 | 188 | 192 | 6000 194 | 195 | 199 | 203 | 8000 205 | 206 | 210 | 214 | 10000 216 | 217 | 221 | 225 | 12000 227 | 228 | 232 | 236 | 14000 238 | 239 | 243 | 247 | 0 249 | 250 | 254 | 258 | 10 260 | 261 | 265 | 269 | 20 271 | 272 | 276 | 280 | 30 282 | 283 | 287 | 291 | 40 293 | 294 | 298 | 302 | 50 304 | 305 | 309 | 313 | 60 315 | 316 | 320 | 324 | 70 326 | 327 | 331 | 335 | 80 337 | 338 | 342 | 346 | 90 348 | 349 | 353 | 357 | 100 359 | 360 | 364 | 368 | Space Occupied (Bytes) 370 | 371 | 375 | Number of Records 377 | 378 | 379 | 381 | gnuplot_plot_1 383 | 386 | 390 | Proposed Graph Storage 392 | 393 | 397 | 398 | 399 | 401 | gnuplot_plot_2 403 | 406 | 410 | Traditional Relational Databases 412 | 413 | 417 | 418 | 419 | 422 | 426 | 427 | 428 | 429 | -------------------------------------------------------------------------------- /Reports/pics/1000.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 31 | 51 | Gnuplot 53 | Produced by GNUPLOT 4.6 patchlevel 4 55 | 57 | 64 | 66 | 70 | 75 | 80 | 85 | 93 | 102 | 109 | 114 | 119 | 124 | 129 | 134 | 139 | 144 | 145 | 148 | 151 | 155 | 159 | 0 161 | 162 | 166 | 170 | 20000 172 | 173 | 177 | 181 | 40000 183 | 184 | 188 | 192 | 60000 194 | 195 | 199 | 203 | 80000 205 | 206 | 210 | 214 | 100000 216 | 217 | 221 | 225 | 120000 227 | 228 | 232 | 236 | 140000 238 | 239 | 243 | 247 | 0 249 | 250 | 254 | 258 | 100 260 | 261 | 265 | 269 | 200 271 | 272 | 276 | 280 | 300 282 | 283 | 287 | 291 | 400 293 | 294 | 298 | 302 | 500 304 | 305 | 309 | 313 | 600 315 | 316 | 320 | 324 | 700 326 | 327 | 331 | 335 | 800 337 | 338 | 342 | 346 | 900 348 | 349 | 353 | 357 | 1000 359 | 360 | 364 | 368 | Space Occupied (Bytes) 370 | 371 | 375 | Number of Records 377 | 378 | 379 | 381 | gnuplot_plot_1 383 | 386 | 390 | Proposed Graph Storage 392 | 393 | 397 | 398 | 399 | 401 | gnuplot_plot_2 403 | 406 | 410 | Traditional Relational Databases 412 | 413 | 417 | 418 | 419 | 422 | 426 | 427 | 428 | 429 | -------------------------------------------------------------------------------- /Reports/pics/10000.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 31 | 51 | Gnuplot 53 | Produced by GNUPLOT 4.6 patchlevel 4 55 | 57 | 64 | 66 | 70 | 75 | 80 | 85 | 93 | 102 | 109 | 114 | 119 | 124 | 129 | 134 | 139 | 144 | 145 | 148 | 151 | 155 | 159 | 0 161 | 162 | 166 | 170 | 200000 172 | 173 | 177 | 181 | 400000 183 | 184 | 188 | 192 | 600000 194 | 195 | 199 | 203 | 800000 205 | 206 | 210 | 214 | 1e+06 216 | 217 | 221 | 225 | 1.2e+06 227 | 228 | 232 | 236 | 1.4e+06 238 | 239 | 243 | 247 | 0 249 | 250 | 254 | 258 | 1000 260 | 261 | 265 | 269 | 2000 271 | 272 | 276 | 280 | 3000 282 | 283 | 287 | 291 | 4000 293 | 294 | 298 | 302 | 5000 304 | 305 | 309 | 313 | 6000 315 | 316 | 320 | 324 | 7000 326 | 327 | 331 | 335 | 8000 337 | 338 | 342 | 346 | 9000 348 | 349 | 353 | 357 | 10000 359 | 360 | 364 | 368 | Space Occupied (Bytes) 370 | 371 | 375 | Number of Records 377 | 378 | 379 | 381 | gnuplot_plot_1 383 | 386 | 390 | Proposed Graph Storage 392 | 393 | 397 | 398 | 399 | 401 | gnuplot_plot_2 403 | 406 | 410 | Traditional Relational Databases 412 | 413 | 417 | 418 | 419 | 422 | 426 | 427 | 428 | 429 | -------------------------------------------------------------------------------- /Reports/pics/90000.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 31 | 51 | Gnuplot 53 | Produced by GNUPLOT 4.6 patchlevel 4 55 | 57 | 64 | 66 | 70 | 75 | 80 | 85 | 93 | 102 | 109 | 114 | 119 | 124 | 129 | 134 | 139 | 144 | 145 | 148 | 151 | 155 | 159 | 0 161 | 162 | 166 | 170 | 2e+06 172 | 173 | 177 | 181 | 4e+06 183 | 184 | 188 | 192 | 6e+06 194 | 195 | 199 | 203 | 8e+06 205 | 206 | 210 | 214 | 1e+07 216 | 217 | 221 | 225 | 1.2e+07 227 | 228 | 232 | 236 | 0 238 | 239 | 243 | 247 | 10000 249 | 250 | 254 | 258 | 20000 260 | 261 | 265 | 269 | 30000 271 | 272 | 276 | 280 | 40000 282 | 283 | 287 | 291 | 50000 293 | 294 | 298 | 302 | 60000 304 | 305 | 309 | 313 | 70000 315 | 316 | 320 | 324 | 80000 326 | 327 | 331 | 335 | 90000 337 | 338 | 342 | 346 | Space Occupied (Bytes) 348 | 349 | 353 | Number of Records 355 | 356 | 357 | 359 | gnuplot_plot_1 361 | 364 | 368 | Proposed Graph Storage 370 | 371 | 375 | 376 | 377 | 379 | gnuplot_plot_2 381 | 384 | 388 | Traditional Relational Databases 390 | 391 | 395 | 396 | 397 | 400 | 404 | 405 | 406 | 407 | -------------------------------------------------------------------------------- /Reports/pics/graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bug-Assassins/Relational-Graph-Database/277e44d7ec899441fd3afdc6af513f8cbc9ee118/Reports/pics/graph.png -------------------------------------------------------------------------------- /Reports/pics/nitk_logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bug-Assassins/Relational-Graph-Database/277e44d7ec899441fd3afdc6af513f8cbc9ee118/Reports/pics/nitk_logo.jpg -------------------------------------------------------------------------------- /Reports/pics/time.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 31 | 51 | Gnuplot 53 | Produced by GNUPLOT 4.6 patchlevel 4 55 | 57 | 64 | 66 | 70 | 75 | 80 | 85 | 93 | 102 | 109 | 114 | 119 | 124 | 129 | 134 | 139 | 144 | 145 | 148 | 151 | 155 | 159 | 0 161 | 162 | 166 | 170 | 2000 172 | 173 | 177 | 181 | 4000 183 | 184 | 188 | 192 | 6000 194 | 195 | 199 | 203 | 8000 205 | 206 | 210 | 214 | 10000 216 | 217 | 221 | 225 | 0 227 | 228 | 232 | 236 | 200 238 | 239 | 243 | 247 | 400 249 | 250 | 254 | 258 | 600 260 | 261 | 265 | 269 | 800 271 | 272 | 276 | 280 | 1000 282 | 283 | 287 | 291 | Number of Record Access Required 293 | 294 | 298 | Number of records in Child Table 300 | 301 | 302 | 304 | gnuplot_plot_1 306 | 309 | 313 | Tradional Relational Databases (100) 315 | 316 | 319 | 320 | 321 | 323 | gnuplot_plot_2 325 | 328 | 332 | Proposed Model (100) 334 | 335 | 339 | 340 | 341 | 343 | gnuplot_plot_3 345 | 348 | 352 | Traditional Relational Database (50) 354 | 355 | 359 | 360 | 361 | 363 | gnuplot_plot_4 365 | 368 | 372 | Tradional Relational Database (25) 374 | 375 | 379 | 380 | 381 | 384 | 388 | 389 | 390 | 391 | -------------------------------------------------------------------------------- /Reports/pics/trie.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 13 | 19 | 24 | 25 | 31 | 36 | 37 | 38 | 43 | 51 | 59 | 67 | 75 | 83 | 91 | 99 | 107 | i 116 | t 125 | e 134 | o 143 | n 152 | n 161 | n 170 | a 179 | t 188 | i 197 | in 206 | inn 215 | te 224 | tea 233 | ten 242 | to 251 | 3 260 | 12 269 | 9 278 | 7 287 | 5 296 | 11 305 | 309 | 313 | 316 | 320 | 324 | 325 | 328 | 332 | 336 | 337 | 345 | 353 | 361 | 369 | 377 | 385 | 388 | 392 | 396 | 397 | ted 406 | d 415 | A 424 | 432 | 440 | A 449 | 15 458 | 4 467 | 468 | -------------------------------------------------------------------------------- /Reports/tikz-er2.sty: -------------------------------------------------------------------------------- 1 | % The tikz-er2 package. 2 | % Ver. 1.0 3 | % (c) Pável Caldo 4 | % January 2009 5 | 6 | \NeedsTeXFormat{LaTeX2e} 7 | \ProvidesPackage{tikz-er2}[2009/01/31 Entity-relationship diagrams using the 8 | Tikz library] 9 | 10 | \RequirePackage{tikz} 11 | \RequirePackage[normalem]{ulem} % for the dashed underline 12 | 13 | \usetikzlibrary{shapes.geometric} 14 | \usetikzlibrary{arrows} 15 | \usetikzlibrary{fit} 16 | 17 | \tikzstyle{every entity} = [] 18 | \tikzstyle{every weak entity} = [] 19 | \tikzstyle{every attribute} = [] 20 | \tikzstyle{every relationship} = [] 21 | \tikzstyle{every link} = [] 22 | \tikzstyle{every isa} = [] 23 | 24 | \tikzstyle{link} = [>=triangle 60, draw, thick, every link] 25 | 26 | \tikzstyle{total} = [link, double, double distance=3pt] 27 | 28 | \tikzstyle{entity} = [rectangle, draw, black, very thick, 29 | minimum width=6em, minimum height=3em, 30 | every entity] 31 | 32 | \tikzstyle{weak entity} = [entity, double, double distance=2pt, 33 | every weak entity] 34 | 35 | \tikzstyle{attribute} = [ellipse, draw, black, very thick, 36 | minimum width=5em, minimum height=2em, 37 | every attribute] 38 | 39 | %\tikzstyle{key attribute} = [attribute, font=\bfseries] 40 | 41 | \tikzstyle{multi attribute} = [attribute, double, double distance=2pt] 42 | 43 | \tikzstyle{derived attribute} = [attribute, dashed] 44 | 45 | %\tikzstyle{discriminator} = [attribute, font=\itshape] 46 | 47 | \tikzstyle{relationship} = [diamond, draw, black, very thick, 48 | minimum width=2em, aspect=1, 49 | every relationship] 50 | 51 | \tikzstyle{ident relationship} = [relationship, double, double distance=2pt] 52 | 53 | \tikzstyle{isa} = [isosceles triangle, isosceles triangle apex angle=60, 54 | shape border rotate=-90, 55 | draw, black, very thick, minimum size=3em, 56 | every isa] 57 | 58 | % for text un key attributes 59 | \newcommand{\key}[1]{\underline{#1}} 60 | 61 | % for text in discriminator attributes 62 | \def\discriminator{\bgroup 63 | \ifdim\ULdepth=\maxdimen % Set depth based on font, if not set already 64 | \settodepth\ULdepth{(j}\advance\ULdepth.4pt\fi 65 | \markoverwith{\kern.15em 66 | \vtop{\kern\ULdepth \hrule width .3em}% 67 | \kern.15em}\ULon} -------------------------------------------------------------------------------- /src/database.h: -------------------------------------------------------------------------------- 1 | #ifndef DATABASE_INCLUDED 2 | #define DATABASE_INCLUDED 1 3 | 4 | #include "table.h" 5 | 6 | class database { 7 | 8 | private: 9 | std::string name; 10 | std::vector tables; 11 | 12 | public: 13 | 14 | //Constructor that creates a new database with given name 15 | database(std::string db_name) 16 | { 17 | name = db_name; 18 | } 19 | 20 | //Function that adds a table to the database 21 | void add_table(table *tab) 22 | { 23 | tables.push_back(tab); 24 | } 25 | 26 | table *get_table(unsigned int i) 27 | { 28 | if (i > tables.size()) 29 | return NULL; 30 | 31 | return tables[i]; 32 | } 33 | 34 | unsigned int get_tables_size() 35 | { 36 | return tables.size(); 37 | } 38 | 39 | unsigned int get_index_table(table *tab) 40 | { 41 | unsigned int i; 42 | 43 | for (i = 0; i < tables.size(); i++) 44 | { 45 | if (tables[i] == tab) 46 | return i; 47 | } 48 | return -1; 49 | } 50 | 51 | // Function to check whether a table "name" exists or not and returns the index of the table 52 | // Function returns -1 to indicate that the table does not exist 53 | int check_tab_name(std::string name) 54 | { 55 | int i; 56 | std::transform(name.begin(), name.end(), name.begin(), toupper); 57 | for (i = 0; i < tables.size(); i++) 58 | { 59 | if (tables[i]->get_table_name().compare(name) == 0) 60 | { 61 | printf("Table = %s\n", tables[i]->get_table_name().c_str()); 62 | return i; 63 | } 64 | } 65 | return -1; 66 | } 67 | //Function to deallocate the database 68 | void clear() 69 | { 70 | unsigned int i; 71 | 72 | name.clear(); 73 | for(i = 0; i < tables.size(); i++) 74 | { 75 | tables[i]->clear(); 76 | delete tables[i]; 77 | } 78 | tables.clear(); 79 | } 80 | }; 81 | 82 | #endif // DATABASE_INCLUDED 83 | -------------------------------------------------------------------------------- /src/domain.h: -------------------------------------------------------------------------------- 1 | #ifndef META_INCLUDED 2 | #define META_INCLUDED 1 3 | 4 | class table; 5 | class attribute_node; 6 | 7 | #include "nodes.h" 8 | #include "trie.h" 9 | 10 | 11 | class domain { 12 | 13 | private: 14 | unsigned int data_type; 15 | std::vector
table_list; 16 | attribute_node *head; 17 | trie *index; 18 | 19 | public: 20 | 21 | static const unsigned int INTEGER = 1; 22 | static const unsigned int STRING = 2; 23 | static const unsigned int FLOAT = 3; 24 | 25 | //Constructor for a new domain 26 | domain(unsigned int type) 27 | { 28 | data_type = type; 29 | index = new trie(); 30 | head = NULL; 31 | } 32 | 33 | //Function to get and set data type 34 | unsigned int get_data_type() 35 | { 36 | return data_type; 37 | } 38 | 39 | //Function to get trie Index 40 | trie *get_index() 41 | { 42 | return index; 43 | } 44 | 45 | unsigned int insert_table_pointer(table *tab) 46 | { 47 | table_list.push_back(tab); 48 | return (table_list.size() - 1); 49 | } 50 | 51 | unsigned int get_table_index(table *tab) 52 | { 53 | unsigned int i; 54 | 55 | for(i = 0; i < table_list.size(); i++) 56 | { 57 | if(table_list[i] == tab) 58 | { 59 | return i; 60 | } 61 | } 62 | return -1; 63 | } 64 | 65 | //Function to add new value to domain 66 | attribute_node* add_get_new_value(std::string &new_val, main_node *node, unsigned int tab_index, bool ins, size_t &node_size) 67 | { 68 | bool exists = false; 69 | 70 | //Add the new value to trie for indexing 71 | attribute_node* new_node = index->get_node(new_val, exists, table_list.size()); 72 | 73 | //Add the new node to domain 74 | if(head == NULL) 75 | { 76 | head = new_node; 77 | node_size += sizeof(attribute_node *) + new_val.length(); 78 | } 79 | else if(!exists) 80 | { 81 | new_node->set_next(head); 82 | head = new_node; 83 | node_size += sizeof(attribute_node *) + new_val.length(); 84 | } 85 | new_node->connect_main_record(node, tab_index); 86 | if(ins) 87 | node->add_attribute(new_node); 88 | return new_node; 89 | } 90 | 91 | // Function to get the list of main nodes connected to a specific attribute node which belong to the given table. 92 | std::vector< main_node * > *get_main_nodes(std::string &value, unsigned int table_index) 93 | { 94 | bool exists = true; 95 | attribute_node *node = index->get_node(value, exists, table_list.size()); 96 | 97 | if(!node) 98 | { 99 | return NULL; 100 | } 101 | 102 | return node->get_record_list(table_index); 103 | 104 | } 105 | 106 | //Function to deallocate the whole domain 107 | void clear() 108 | { 109 | attribute_node* temp = head; 110 | 111 | while(head != NULL) 112 | { 113 | temp = head->get_next(); 114 | head->clear(); 115 | delete head; 116 | head = temp; 117 | } 118 | index->clear(); 119 | delete index; 120 | } 121 | }; 122 | 123 | #endif // META_INCLUDED 124 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #define VERBOSE 1 2 | #define DEBUG 1 3 | #define TEST 1 4 | 5 | #include 6 | 7 | #include "database.h" 8 | #include "select.h" 9 | 10 | #ifdef TEST 11 | #include "test.h" 12 | #endif 13 | 14 | int print_table_details(database *main_database) 15 | { 16 | table *temp_table; 17 | unsigned int i, index, att_count; 18 | int temp_int; 19 | 20 | if (VERBOSE) 21 | { 22 | printf("Enter the table you want\n"); 23 | for (i = 0; i < main_database->get_tables_size(); i++) 24 | { 25 | printf("%d : %s\n", i + 1, main_database->get_table(i)->get_table_name().c_str()); 26 | } 27 | } 28 | scanf("%d", &index); 29 | printf("\n"); 30 | 31 | temp_table = main_database->get_table(index - 1); 32 | att_count = temp_table->get_attribute_count(); 33 | 34 | if (VERBOSE) 35 | { 36 | for (i = 0; i < att_count; i++) 37 | { 38 | 39 | printf ("%s\t", temp_table->get_attribute_name(i).c_str()); 40 | temp_int = temp_table->get_normal_index(i)->get_data_type(); 41 | if (temp_int == 1) 42 | printf("INTEGER\n"); 43 | else if (temp_int == 2) 44 | printf("STRING\n"); 45 | else 46 | printf("FLOAT\n"); 47 | } 48 | } 49 | 50 | return index - 1; 51 | } 52 | void print_record_list(table *tab, std::set< main_node *> &record_list, std::vector< int > &attributes) 53 | { 54 | unsigned int i, j; 55 | std::set< main_node * >::iterator it; 56 | 57 | printf("\n--------------------------------------------------------------------------------\n"); 58 | //Printing the heading of each column 59 | for(i = 0; i < attributes.size(); i++) 60 | { 61 | printf("%s\t", tab->get_attribute_name(attributes[i]).c_str()); 62 | } 63 | printf("\n--------------------------------------------------------------------------------\n"); 64 | 65 | //Printing the Actual Records 66 | for(it = record_list.begin(); it != record_list.end(); it++) 67 | { 68 | for(j = 0; j < attributes.size(); j++) 69 | { 70 | printf("%s\t", (*it)->get_attribute_list_index(attributes[j])->get_value().c_str()); 71 | } 72 | printf("\n"); 73 | } 74 | printf("--------------------------------------------------------------------------------\n"); 75 | 76 | return; 77 | } 78 | 79 | void create_table(database *main_database) 80 | { 81 | std::string temp_str; 82 | std::vector< unsigned int > type; 83 | std::vector< std::string > attribute_names; 84 | std::vector< int > fk_list; 85 | char temp_name[100]; 86 | int attribute_count, i, j, pkey_span, temp_int, fk_count, table_index; 87 | unsigned int temp_type; 88 | table *temp_table, *temp_table2; 89 | 90 | if (VERBOSE) 91 | printf("Enter the table name:"); 92 | 93 | scanf("%s", temp_name); 94 | temp_str.assign(temp_name); 95 | std::transform(temp_str.begin(), temp_str.end(), temp_str.begin(), toupper); 96 | 97 | 98 | if (VERBOSE) 99 | printf("Enter the number of attributes:"); 100 | 101 | scanf("%d", &attribute_count); 102 | 103 | temp_table = new table(temp_str, attribute_count); 104 | bool *ins_check = new bool[attribute_count]; 105 | 106 | for (i = 0; i < attribute_count; i++) 107 | { 108 | ins_check[i] = false; 109 | 110 | if (VERBOSE) 111 | printf("Enter the attribute name, type (1: INTEGER 2: STRING 3: FLOAT) :"); 112 | 113 | scanf("%s %u", temp_name, &temp_type); 114 | temp_str.assign(temp_name); 115 | std::transform(temp_str.begin(), temp_str.end(), temp_str.begin(), toupper); 116 | attribute_names.push_back(temp_str); 117 | type.push_back(temp_type); 118 | } 119 | 120 | if (VERBOSE) 121 | printf("Enter the number of columns in primary key:"); 122 | 123 | scanf("%d", &pkey_span); 124 | 125 | if (VERBOSE) 126 | printf("Enter the indices of %d primary key column(s)\n", pkey_span); 127 | 128 | for (i = 0; i < pkey_span; i++) 129 | { 130 | scanf("%d", &temp_int); 131 | temp_table->add_primary_key(temp_int - 1); 132 | } 133 | 134 | if (VERBOSE) 135 | printf("Enter the number of table the foreign key spans:"); 136 | 137 | scanf("%d", &fk_count); 138 | 139 | for (i = 0; i < fk_count; i++) 140 | { 141 | table_index = print_table_details(main_database); 142 | fk_list.clear(); 143 | temp_table2 = main_database->get_table(table_index); 144 | 145 | for (j = 0; j < temp_table2->get_primary_key_size(); j++) 146 | { 147 | scanf("%d", &temp_int); 148 | temp_int--; 149 | ins_check[temp_int] = true; 150 | temp_table->add_foreign_domain(attribute_names[temp_int], temp_table2->get_domain(i), temp_int); 151 | fk_list.push_back(temp_int); 152 | } 153 | 154 | temp_table->add_foreign_key(temp_table2, fk_list); 155 | } 156 | 157 | for (i = 0; i < attribute_count; i++) 158 | { 159 | if(ins_check[i] == false) 160 | { 161 | temp_table->add_attribute(type[i], attribute_names[i], i); 162 | } 163 | } 164 | 165 | delete[] ins_check; 166 | fk_list.clear(); 167 | temp_table->add_to_size(sizeof(*temp_table)); 168 | main_database->add_table(temp_table); 169 | 170 | return; 171 | } 172 | 173 | void insert_to_table(database *main_database) 174 | { 175 | int index, success = -1; 176 | char temp_char_arr[100]; 177 | std::string temp_string; 178 | table *temp_table; 179 | 180 | printf("Enter table name:"); 181 | fflush(stdout); 182 | scanf("%s", temp_char_arr); 183 | temp_string.assign(temp_char_arr); 184 | index = main_database->check_tab_name(temp_string); 185 | if (index == -1) 186 | { 187 | printf("Wrong table name\n"); 188 | return; 189 | } 190 | temp_table = main_database->get_table(index); 191 | 192 | std::vector< std::string > values(temp_table->get_attribute_count()); 193 | 194 | if (VERBOSE) 195 | { 196 | printf("Enter column name, value pair. Enter 0 to finish entering info\n"); 197 | } 198 | 199 | while (1) 200 | { 201 | scanf("%s", temp_char_arr); 202 | temp_string.assign(temp_char_arr); 203 | index = temp_table->check_column_name(temp_string); 204 | if (index == -1) 205 | break; 206 | scanf("%s", temp_char_arr); 207 | values[index].assign(temp_char_arr); 208 | } 209 | 210 | success = temp_table->add_new_record(values); 211 | if(success == 1) 212 | { 213 | printf("1 Row Inserted\n"); 214 | } 215 | else if(success == -1) 216 | { 217 | printf("NULL Primary Key not allowed\n"); 218 | } 219 | else if (success == 0) 220 | { 221 | printf("Primary Key already exists\n"); 222 | } 223 | else if (success == -2) 224 | { 225 | printf("Integrity Violation\n"); 226 | } 227 | values.clear(); 228 | 229 | } 230 | 231 | void print_table(database *main_database) 232 | { 233 | int attribute_count, i, index; 234 | table *temp_table; 235 | main_node *temp_main_node, *next_node; 236 | char temp_char_arr[100]; 237 | std::string temp_string; 238 | 239 | printf("Enter the name of table:"); 240 | fflush(stdout); 241 | scanf("%s", temp_char_arr); 242 | printf("\n"); 243 | temp_string.assign(temp_char_arr); 244 | index = main_database->check_tab_name(temp_string); 245 | if (index == -1) 246 | { 247 | printf("Table does not exist\n"); 248 | return; 249 | } 250 | 251 | temp_table = main_database->get_table(index); 252 | temp_main_node = temp_table->get_main_node_head(); 253 | attribute_count = temp_table->get_attribute_count(); 254 | 255 | printf("\n--------------------------------------------------------------------------------\n"); 256 | for (i = 0; i < attribute_count; i++) 257 | { 258 | printf("%s\t", temp_table->get_attribute_name(i).c_str()); 259 | } 260 | printf("\n--------------------------------------------------------------------------------\n"); 261 | 262 | while(temp_main_node && temp_main_node->lazy_delete()) 263 | { 264 | next_node = temp_main_node; 265 | temp_main_node = temp_main_node->get_next(); 266 | delete next_node; 267 | } 268 | 269 | temp_table->set_main_node_head(temp_main_node); 270 | 271 | if(temp_main_node == NULL) return; 272 | 273 | for (i = 0; i < attribute_count; i++) 274 | { 275 | printf("%s\t", temp_main_node->get_attribute_list_index(i)->get_value().c_str()); 276 | } 277 | printf("\n"); 278 | 279 | next_node = temp_main_node->get_next(); 280 | while (next_node) 281 | { 282 | if(next_node->lazy_delete()) 283 | { 284 | temp_main_node->delete_next(); 285 | } 286 | 287 | else 288 | { 289 | for (i = 0; i < attribute_count; i++) 290 | { 291 | printf("%s\t", next_node->get_attribute_list_index(i)->get_value().c_str()); 292 | } 293 | printf("\n"); 294 | temp_main_node = next_node; 295 | } 296 | next_node = temp_main_node->get_next(); 297 | } 298 | printf("\n--------------------------------------------------------------------------------\n"); 299 | } 300 | 301 | void query(database *main_database, int check) 302 | { 303 | 304 | /*Conditions on check 305 | 0 : select 306 | 1 : update 307 | 2 : delete 308 | */ 309 | 310 | std::vector< int > col_list, attributes, ops; 311 | std::vector< value_expression > expression; 312 | std::vector< std::string > values, update_values; 313 | std::vector < std::vector< value_expression > > expression_vec; 314 | 315 | std::set< main_node * > result; 316 | 317 | int col_count, temp_int, expr_count = 0, join_operator, i; 318 | char rhs[100], lhs[100], op_string[100]; 319 | std::string temp_string; 320 | value_expression temp_exp; 321 | char t_name[100], col_name[100], temp_char_arr[100]; 322 | 323 | 324 | printf("\nEnter the table name: "); 325 | fflush(stdout); 326 | scanf("%s", t_name); 327 | temp_string.assign(t_name); 328 | int table_index = main_database->check_tab_name(temp_string); 329 | if (table_index == -1) 330 | { 331 | printf("Wrong table name\n"); 332 | return; 333 | } 334 | table *selected_table = main_database->get_table(table_index); 335 | printf("\n"); 336 | if(check < 2) 337 | { 338 | if (VERBOSE) 339 | { 340 | if(check == 1) 341 | printf("Enter the number of columns you want to update: "); 342 | else if(check == 0) 343 | printf("Enter the number of columns you want to select: "); 344 | fflush(stdout); 345 | } 346 | 347 | scanf("%d", &col_count); 348 | 349 | if (VERBOSE) 350 | { 351 | printf("Enter the column name(s)"); 352 | if(check == 1) 353 | printf(" and their corresponding value(s)"); 354 | printf(":\n"); 355 | } 356 | 357 | for (i = 0; i < col_count; i++) 358 | { 359 | scanf("%s", col_name); 360 | temp_string.assign(col_name); 361 | temp_int = selected_table->check_column_name(temp_string); 362 | if (temp_int == -1) 363 | { 364 | printf("Wrong column\n"); 365 | } 366 | col_list.push_back(temp_int); 367 | if(check == 1) 368 | { 369 | scanf("%s", rhs); 370 | temp_string.assign(rhs); 371 | update_values.push_back(temp_string); 372 | } 373 | } 374 | } 375 | 376 | if (VERBOSE) 377 | printf("\nEnter the number of conditions:"); 378 | fflush(stdout); 379 | 380 | scanf("%d", &expr_count); 381 | 382 | for (i = 0; i < expr_count; i++) 383 | { 384 | if (VERBOSE) 385 | { 386 | printf("Enter condition no. %d:", i + 1); 387 | fflush(stdout); 388 | } 389 | scanf("%s %s %s", lhs, op_string, rhs); 390 | temp_exp.value.assign(rhs); 391 | 392 | temp_string.assign(lhs); 393 | temp_int = selected_table->check_column_name(temp_string); 394 | if (temp_int == -1) 395 | { 396 | printf("Wrong column name\n"); 397 | return; 398 | } 399 | temp_exp.attribute = temp_int; 400 | 401 | temp_string.assign(op_string); 402 | if (temp_string.compare("=") == 0) 403 | temp_exp.op = 0; 404 | else if (temp_string.compare("<=") == 0) 405 | temp_exp.op = 1; 406 | else if (temp_string.compare(">=") == 0) 407 | temp_exp.op = 2; 408 | else if (temp_string.compare("!=") == 0) 409 | temp_exp.op = 3; 410 | else if (temp_string.compare(">") == 0) 411 | temp_exp.op = 4; 412 | else if (temp_string.compare("<") == 0) 413 | temp_exp.op = 5; 414 | else 415 | { 416 | printf("Wrong operation\n"); 417 | return; 418 | } 419 | 420 | expression.push_back(temp_exp); 421 | 422 | if (i != expr_count - 1) 423 | { 424 | if (VERBOSE) 425 | printf("AND/OR ? :"); 426 | fflush(stdout); 427 | 428 | scanf("%s", temp_char_arr); 429 | temp_string.assign(temp_char_arr); 430 | if (temp_string.compare("AND") == 0) 431 | join_operator = 1; 432 | else if(temp_string.compare("OR") == 0) 433 | join_operator = 0; 434 | else 435 | { 436 | printf("Wrong option\n"); 437 | return; 438 | } 439 | 440 | if(join_operator == 0) 441 | { 442 | expression_vec.push_back(expression); 443 | expression.clear(); 444 | } 445 | } 446 | } 447 | 448 | if(expr_count) 449 | { 450 | expression_vec.push_back(expression); 451 | expression.clear(); 452 | } 453 | 454 | else 455 | { 456 | switch(check) 457 | { 458 | case 0: 459 | selected_table->select_all(col_list); 460 | break; 461 | case 1: 462 | selected_table->update_all(col_list, update_values); 463 | break; 464 | case 2: 465 | selected_table->delete_all(); 466 | break; 467 | default: 468 | printf("Wrong query condition\n"); 469 | } 470 | return; 471 | } 472 | 473 | result = selected_table->select_single_table(expression_vec); 474 | 475 | if(check == 0) 476 | { 477 | print_record_list(selected_table, result, col_list); 478 | } 479 | else if(check == 1) 480 | { 481 | selected_table->update(result, col_list, update_values); 482 | } 483 | else if(check == 2) 484 | { 485 | selected_table->del(result); 486 | } 487 | } 488 | void print_main_node(main_node *result, std::vector< int > &col_list) 489 | { 490 | unsigned int i; 491 | 492 | for (i = 0; i < col_list.size(); i++) 493 | { 494 | printf("%s\t", result->get_attribute_list_index(col_list[i])->get_value().c_str()); 495 | } 496 | return; 497 | } 498 | void join_tables(database *main_database) 499 | { 500 | table *j_table[2], *temp_table; 501 | int j_index[2], table_span, i, foreign_key_index, expr_count, j, col_index, tab, op_type, j_type, t_index, col_count; 502 | struct value_expression temp_expression; 503 | std::vector< std::vector< value_expression > > expression_vec; 504 | std::vector< value_expression > temp_expr_vect; 505 | std::vector< int > col_list[2]; 506 | std::set< main_node * > result; 507 | std::set< main_node * >::iterator it; 508 | main_node *node; 509 | std::string temp_string; 510 | char t_name[100], col_name[100], temp_char_arr[500]; 511 | char lhs[100], op_string[4], rhs[100]; 512 | 513 | printf("\nEnter the child table name:"); 514 | fflush(stdout); 515 | scanf("%s", t_name); 516 | temp_string.assign(t_name); 517 | j_index[0] = main_database->check_tab_name(temp_string); 518 | if (j_index[0] == -1) 519 | { 520 | printf("Wrong table name\n"); 521 | return; 522 | } 523 | 524 | j_table[0] = main_database->get_table(j_index[0]); 525 | table_span = j_table[0]->get_foreign_key_count(); 526 | 527 | printf("Enter the parent table name:"); 528 | fflush(stdout); 529 | scanf("%s", t_name); 530 | temp_string.assign(t_name); 531 | foreign_key_index = j_table[0]->check_parent_name(temp_string); 532 | if (foreign_key_index == -1) 533 | { 534 | printf("Wrong parent name\n"); 535 | return; 536 | } 537 | j_index[1] = main_database->get_index_table(j_table[0]->get_parent_table(foreign_key_index)); 538 | j_table[1] = main_database->get_table(j_index[1]); 539 | 540 | printf("\nEnter the number of columns you want to select:"); 541 | fflush(stdout); 542 | scanf("%d", &col_count); 543 | 544 | for (i = 0; i < col_count; i++) 545 | { 546 | printf("\nColumn name(TABLE.COLUMN_NAME) : "); 547 | fflush(stdout); 548 | scanf("%s", temp_char_arr); 549 | temp_string.assign(temp_char_arr); 550 | t_index = main_database->check_tab_name(temp_string.substr(0, temp_string.find("."))); 551 | 552 | if (t_index == -1) 553 | { 554 | printf("Wrong table name\n"); 555 | return; 556 | } 557 | else if (t_index == j_index[0]) 558 | { 559 | t_index = 0; 560 | } 561 | else if (t_index == j_index[1]) 562 | { 563 | t_index = 1; 564 | } 565 | else 566 | { 567 | printf("This table was not selected\n"); 568 | return; 569 | } 570 | 571 | temp_string.assign(temp_string.substr(temp_string.find(".") + 1)); 572 | col_index = j_table[t_index]->check_column_name(temp_string); 573 | if (col_index == -1) 574 | { 575 | printf("Wrong column selected\n"); 576 | return; 577 | } 578 | col_list[t_index].push_back(col_index); 579 | } 580 | 581 | printf("\nEnter the number of conditions:"); 582 | fflush(stdout); 583 | scanf("%d", &expr_count); 584 | 585 | j = 0; 586 | for (i = 0; i < expr_count; i++) 587 | { 588 | 589 | printf("\nCondition:"); 590 | fflush(stdout); 591 | scanf("%s %s %s", lhs, op_string, rhs); 592 | temp_string.assign(lhs); 593 | t_index = main_database->check_tab_name(temp_string.substr(0, temp_string.find("."))); 594 | 595 | if (t_index == -1) 596 | { 597 | printf("Wrong table name\n"); 598 | return; 599 | } 600 | else if (t_index == j_index[0]) 601 | { 602 | t_index = 0; 603 | } 604 | else if (t_index == j_index[1]) 605 | { 606 | t_index = 1; 607 | } 608 | else 609 | { 610 | printf("This table was not selected\n"); 611 | return; 612 | } 613 | 614 | temp_string.assign(temp_string.substr(temp_string.find(".") + 1)); 615 | col_index = j_table[t_index]->check_column_name(temp_string); 616 | if (col_index == -1) 617 | { 618 | printf("Wrong column selected\n"); 619 | return; 620 | } 621 | 622 | temp_string.assign(op_string); 623 | if (temp_string.compare("=") == 0) 624 | op_type = 0; 625 | else if (temp_string.compare("<=") == 0) 626 | op_type = 1; 627 | else if (temp_string.compare(">=") == 0) 628 | op_type = 2; 629 | else if (temp_string.compare("!=") == 0) 630 | op_type = 3; 631 | else if (temp_string.compare(">") == 0) 632 | op_type = 4; 633 | else if (temp_string.compare("<") == 0) 634 | op_type = 5; 635 | else 636 | { 637 | printf("Wrong operation\n"); 638 | return; 639 | } 640 | 641 | if (t_index) 642 | temp_expression.table = false; 643 | else 644 | temp_expression.table = true; 645 | 646 | temp_expression.attribute = col_index; 647 | temp_expression.op = op_type; 648 | temp_expression.value.assign(rhs); 649 | 650 | temp_expr_vect.push_back(temp_expression); 651 | 652 | if (i != expr_count - 1) 653 | { 654 | printf("AND/OR: "); 655 | fflush(stdout); 656 | scanf("%s", temp_char_arr); 657 | temp_string.assign(temp_char_arr); 658 | if (temp_string.compare("AND") == 0) 659 | j_type = 1; 660 | else if(temp_string.compare("OR") == 0) 661 | j_type = 0; 662 | else 663 | { 664 | printf("Wrong option\n"); 665 | return; 666 | } 667 | 668 | if (j_type == 0) 669 | { 670 | j++; 671 | expression_vec.push_back(temp_expr_vect); 672 | temp_expr_vect.clear(); 673 | } 674 | } 675 | } 676 | expression_vec.push_back(temp_expr_vect); 677 | temp_expr_vect.clear(); 678 | result = j_table[0]->join(foreign_key_index, expression_vec); 679 | for (i = 0; i < col_list[0].size(); i++) 680 | { 681 | printf("%s.", j_table[0]->get_table_name().c_str()); 682 | printf("%s ", j_table[0]->get_attribute_name(col_list[0][i]).c_str()); 683 | } 684 | for (i = 0; i < col_list[1].size(); i++) 685 | { 686 | printf("%s.", j_table[1]->get_table_name().c_str()); 687 | printf("%s ", j_table[1]->get_attribute_name(col_list[1][i]).c_str()); 688 | } 689 | printf("\n"); 690 | 691 | 692 | for (it = result.begin(); it != result.end(); it++) 693 | { 694 | node = *it; 695 | print_main_node(node, col_list[0]); 696 | print_main_node(node->get_parent_node(foreign_key_index), col_list[1]); 697 | printf("\n"); 698 | } 699 | 700 | 701 | for (i = 0; i < (int) expression_vec.size(); i++) 702 | expression_vec[i].clear(); 703 | 704 | expression_vec.clear(); 705 | col_list[0].clear(); 706 | col_list[1].clear(); 707 | result.clear(); 708 | } 709 | 710 | int main() 711 | { 712 | int choice; 713 | char name[100]; 714 | 715 | if (VERBOSE) 716 | printf("Enter name of database:"); 717 | 718 | scanf("%s", name); 719 | 720 | database *main_database = new database(std::string(name)); 721 | 722 | #ifdef TEST 723 | create_dept(main_database); 724 | create_emp(main_database); 725 | insert_dept(main_database); 726 | insert_emp(main_database); 727 | #endif 728 | 729 | 730 | while (1) 731 | { 732 | if (VERBOSE) 733 | { 734 | printf("\n"); 735 | printf("Enter your choice :\n"); 736 | printf("1) Create a table\n"); 737 | printf("2) Insert to table\n"); 738 | printf("3) Describe table\n"); 739 | printf("4) Print a table\n"); 740 | printf("5) Select from single table\n"); 741 | printf("6) Update a table\n"); 742 | printf("7) Delete from a table\n"); 743 | printf("8) Join two tables\n"); 744 | printf("0) Exit\n"); 745 | } 746 | scanf("%d", &choice); 747 | 748 | switch (choice) 749 | { 750 | case 1: 751 | create_table(main_database); 752 | break; 753 | 754 | case 2: 755 | insert_to_table(main_database); 756 | break; 757 | 758 | case 3: 759 | print_table_details(main_database); 760 | break; 761 | 762 | case 4: 763 | print_table(main_database); 764 | break; 765 | 766 | case 5: 767 | query(main_database, 0); 768 | break; 769 | 770 | case 6: 771 | query(main_database, 1); 772 | break; 773 | 774 | case 7: 775 | query(main_database, 2); 776 | break; 777 | 778 | case 8: 779 | join_tables(main_database); 780 | break; 781 | 782 | case 0: 783 | printf("Exiting cleanly!\n"); 784 | main_database->clear(); 785 | delete main_database; 786 | break; 787 | 788 | default: 789 | printf("Not supported\n"); 790 | break; 791 | } 792 | if (choice == 0) 793 | break; 794 | } 795 | 796 | return 0; 797 | } 798 | -------------------------------------------------------------------------------- /src/nodes.h: -------------------------------------------------------------------------------- 1 | #ifndef NODE_INCLUDED 2 | #define NODE_INCLUDED 1 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class main_node; 14 | 15 | class attribute_node { 16 | 17 | private: 18 | std::string value; 19 | std::vector< std::vector< main_node * > > nodes; 20 | attribute_node *next; 21 | 22 | public: 23 | 24 | //Constructor 25 | attribute_node(std::string &val, int num_tables) 26 | { 27 | value = val; 28 | next = NULL; 29 | nodes.resize(num_tables); 30 | } 31 | 32 | //Getter and Setter for value of attribute node 33 | void set_value(std::string val) 34 | { 35 | value = val; 36 | } 37 | 38 | std::string get_value() 39 | { 40 | return value; 41 | } 42 | 43 | //Getter and Setter for next pointer 44 | void set_next(attribute_node* n) 45 | { 46 | next = n; 47 | } 48 | 49 | attribute_node* get_next() 50 | { 51 | return next; 52 | } 53 | 54 | //Function to add details of connected record of a given table 55 | void connect_main_record(main_node *node, int tab_index) 56 | { 57 | nodes[tab_index].push_back(node); 58 | } 59 | 60 | //Function to get number of connected records 61 | unsigned int get_num_records(int tab_index) 62 | { 63 | return nodes[tab_index].size(); 64 | } 65 | 66 | std::vector< main_node * > *get_record_list(unsigned int table_index) 67 | { 68 | if(table_index < 0 || table_index > nodes.size()) 69 | { 70 | printf("Passed Table index %d do not exist !!\nAborting!!", table_index); 71 | fflush(stdout); 72 | abort(); 73 | } 74 | 75 | return &nodes[table_index]; 76 | } 77 | 78 | void delete_edge(main_node *tab_node, int index) 79 | { 80 | nodes[index].erase(std::remove(nodes[index].begin(), nodes[index].end(), tab_node), nodes[index].end()); 81 | } 82 | //Function to clear the node 83 | void clear() 84 | { 85 | unsigned int i; 86 | 87 | value.clear(); 88 | for(i = 0; i < nodes.size(); i++) 89 | { 90 | nodes[i].clear(); 91 | } 92 | nodes.clear(); 93 | } 94 | 95 | }; 96 | 97 | class main_node { 98 | 99 | private: 100 | std::vector< attribute_node * > attribute_list; 101 | main_node *next; 102 | std::vector< main_node * > parent_table_list; 103 | bool marked; 104 | 105 | public: 106 | 107 | main_node() 108 | { 109 | next = NULL; 110 | marked = false; 111 | } 112 | 113 | //Getter and Setter for next node 114 | void set_next(main_node* next_node) 115 | { 116 | next = next_node; 117 | } 118 | 119 | main_node* get_next() 120 | { 121 | return next; 122 | } 123 | 124 | main_node *get_parent_node(int fk_index) 125 | { 126 | return parent_table_list[fk_index]; 127 | } 128 | 129 | size_t get_size() 130 | { 131 | return sizeof(main_node *) + (sizeof(attribute_node *) * attribute_list.size()) 132 | + (sizeof(main_node *) * parent_table_list.size()); 133 | } 134 | 135 | //Function to return the corresponding connected attribute node 136 | attribute_node *get_attribute_list_index(unsigned int attribute_index) 137 | { 138 | if(attribute_index < 0 || attribute_index > attribute_list.size()) 139 | { 140 | printf("Passed attribute index %d do not exist !!\nAborting!!", attribute_index); 141 | fflush(stdout); 142 | abort(); 143 | } 144 | return attribute_list[attribute_index]; 145 | } 146 | 147 | //Function to get an attribute node value 148 | std::string get_attribute_value(int attribute_index) 149 | { 150 | return get_attribute_list_index(attribute_index)->get_value(); 151 | } 152 | 153 | //Function to return all the main_nodes in the child table 154 | std::vector< main_node *> *get_child_table_records(int attribute_index, int index_in_domain) 155 | { 156 | return get_attribute_list_index(attribute_index)->get_record_list(index_in_domain); 157 | } 158 | 159 | std::vector< attribute_node * > *get_attribute_list() 160 | { 161 | return &attribute_list; 162 | } 163 | 164 | //Function to add attribute to the main node 165 | void add_attribute(attribute_node* attr) 166 | { 167 | attribute_list.push_back(attr); 168 | } 169 | 170 | void update_attribute(int index, attribute_node *value) 171 | { 172 | attribute_list[index] = value; 173 | } 174 | 175 | void add_foreign_key_link(main_node *fk) 176 | { 177 | parent_table_list.push_back(fk); 178 | } 179 | 180 | bool lazy_delete() 181 | { 182 | return marked; 183 | } 184 | 185 | void delete_next() 186 | { 187 | main_node *temp; 188 | temp = next; 189 | next = temp->get_next(); 190 | delete temp; 191 | } 192 | 193 | void del_node() 194 | { 195 | marked = true; 196 | clear(); 197 | } 198 | 199 | //Function to deallocate memory 200 | void clear() 201 | { 202 | attribute_list.clear(); 203 | parent_table_list.clear(); 204 | } 205 | }; 206 | 207 | #endif // NODE_INCLUDED 208 | -------------------------------------------------------------------------------- /src/select.h: -------------------------------------------------------------------------------- 1 | #ifndef SELECT_INCLUDED 2 | #define SELECT_INCLUDED 1 3 | 4 | //Funtion to select all records 5 | void table::select_all(std::vector< int > &col_list) 6 | { 7 | int i; 8 | printf("\n--------------------------------------------------------------------------------\n"); 9 | for(i = 0; i < col_list.size(); i++) 10 | { 11 | printf("%s\t", get_attribute_name(col_list[i]).c_str()); 12 | } 13 | printf("\n--------------------------------------------------------------------------------\n"); 14 | 15 | main_node *temp, *temp_main; 16 | 17 | while(head && head->lazy_delete()) 18 | { 19 | temp = head; 20 | head = head->get_next(); 21 | delete temp; 22 | } 23 | 24 | if(head == NULL) return; 25 | 26 | for(i = 0; i < col_list.size(); i++) 27 | { 28 | printf("%s\t", head->get_attribute_list_index(col_list[i])->get_value().c_str()); 29 | } 30 | printf("\n"); 31 | 32 | temp_main = head; 33 | temp = head->get_next(); 34 | 35 | while(temp) 36 | { 37 | if(temp->lazy_delete()) 38 | { 39 | temp_main->delete_next(); 40 | } 41 | 42 | else 43 | { 44 | for (i = 0; i < col_list.size(); i++) 45 | { 46 | printf("%s\t", temp->get_attribute_list_index(col_list[i])->get_value().c_str()); 47 | } 48 | printf("\n"); 49 | temp_main = temp; 50 | } 51 | temp = temp_main->get_next(); 52 | } 53 | printf("\n--------------------------------------------------------------------------------\n"); 54 | } 55 | 56 | //Function to select record from the table given that all logical operators used are AND 57 | std::vector< main_node * > table::select_via_and(std::vector< value_expression > &expression_list) 58 | { 59 | /* 60 | tab = Table on which select operation has to be performed 61 | attributes = indexes of attributes whose values has been specified (size = n) 62 | values = Values with which attribute values has to be matched (size = n) 63 | ops = Operator which has to be using which comparing values (size = n) 64 | All Logical Operators involved is assumed to be AND 65 | */ 66 | 67 | unsigned int i, node_count, min_node_count = INT_MAX; 68 | int min_index = -1; 69 | main_node *temp_main, *temp; 70 | std::vector< main_node * > *main_node_list, *min_main_node_list, result; 71 | 72 | for(i = 0; i < expression_list.size(); i++) 73 | { 74 | //Searching for only EQUAL operators 75 | if(expression_list[i].op == 0) 76 | { 77 | main_node_list = get_records_with_val(expression_list[i].attribute, expression_list[i].value); 78 | 79 | if(main_node_list == NULL) 80 | { 81 | return result; 82 | } 83 | 84 | node_count = main_node_list->size(); 85 | 86 | if(node_count < min_node_count) 87 | { 88 | min_node_count = node_count; 89 | min_main_node_list = main_node_list; 90 | min_index = i; 91 | } 92 | } 93 | } 94 | 95 | if(min_index == -1) 96 | { 97 | /* 98 | This signifies that there was no EQUAL operator in the ops. 99 | Brute Force is the only way to get all nodes 100 | Check for marked nodes for lazy delete 101 | */ 102 | while(head && head->lazy_delete()) 103 | { 104 | temp = head; 105 | head = head->get_next(); 106 | delete temp; 107 | } 108 | 109 | if(head == NULL) return result; 110 | 111 | if(compare_record(head, expression_list)) 112 | { 113 | result.push_back(head); 114 | } 115 | 116 | temp_main = head; 117 | temp = head->get_next(); 118 | 119 | while (temp) 120 | { 121 | if(temp->lazy_delete()) 122 | { 123 | temp_main->delete_next(); 124 | } 125 | 126 | else 127 | { 128 | if(compare_record(temp, expression_list)) 129 | { 130 | result.push_back(temp); 131 | } 132 | temp_main = temp; 133 | } 134 | temp = temp_main->get_next(); 135 | } 136 | 137 | //Returning the list of matched records from brute search 138 | return result; 139 | } 140 | 141 | //This means that at-least one EQUAL operator was found. We Will iterate only through matched records 142 | for(i = 0; i < min_main_node_list->size(); i++) 143 | { 144 | // To avoid extra string comparison skip min_index 145 | if(compare_record((*min_main_node_list)[i], expression_list, min_index)) 146 | { 147 | result.push_back((*min_main_node_list)[i]); 148 | } 149 | } 150 | 151 | //Returning Shortlisted main-nodes that match record 152 | return result; 153 | } 154 | 155 | //Function that executes a generic select query on a single table 156 | std::set< main_node * > table::select_single_table(std::vector< std::vector< value_expression > > &expression_vec) 157 | { 158 | /* 159 | This function accepts a vector of vector. 160 | The inner vectors are all joined by AND operators only. 161 | The other vectors is formed by union 162 | */ 163 | 164 | unsigned int i; 165 | main_node *head; 166 | std::set< main_node * > result; 167 | std::vector< main_node * > temp_result; 168 | 169 | for(i = 0; i < expression_vec.size(); i++) 170 | { 171 | //Finding the result of the first total AND vector 172 | temp_result = select_via_and(expression_vec[i]); 173 | 174 | //Taking union of the current result as well as old result 175 | result.insert(temp_result.begin(), temp_result.end()); 176 | } 177 | 178 | return result; 179 | } 180 | 181 | //Function to return all child nodes connected to a particular main node 182 | std::vector< main_node *> table::get_records_as_child(int foreign_key_index, main_node *parent_record) 183 | { 184 | unsigned int i, j, min_rec_count = INT_MAX, span_index, prime_index, min_index = INT_MAX; 185 | std::vector< main_node * > result, *child_result, *min_child_result; 186 | std::string temp_value; 187 | for(i = 0; i < foreign_key[foreign_key_index].second.size(); i++) 188 | { 189 | span_index = index_in_domain[foreign_key[foreign_key_index].second[i]]; 190 | prime_index = foreign_key[foreign_key_index].first->get_primary_attribute(i); 191 | child_result = parent_record->get_attribute_list_index(prime_index)->get_record_list(span_index); 192 | 193 | if(child_result == NULL) 194 | { 195 | return result; 196 | } 197 | 198 | if(child_result->size() < min_rec_count) 199 | { 200 | min_index = i; 201 | min_rec_count = child_result->size(); 202 | min_child_result = child_result; 203 | } 204 | } 205 | 206 | for(i = 0; i < min_child_result->size(); i++) 207 | { 208 | for(j = 0; j < foreign_key[foreign_key_index].second.size(); j++) 209 | { 210 | if(j != min_index) 211 | { 212 | span_index = foreign_key[foreign_key_index].second[j]; 213 | prime_index = foreign_key[foreign_key_index].first->get_primary_attribute(j); 214 | temp_value = (*min_child_result)[i]->get_attribute_value(span_index); 215 | if(temp_value.compare(parent_record->get_attribute_value(prime_index)) != 0) 216 | { 217 | break; 218 | } 219 | } 220 | } 221 | 222 | if(j == foreign_key[foreign_key_index].second.size()) 223 | { 224 | result.push_back((*min_child_result)[i]); 225 | } 226 | 227 | } 228 | 229 | return result; 230 | } 231 | 232 | //Function to get all child node connected to any node in parent result set 233 | //This function Assumes all logical operators used is AND 234 | std::vector< main_node *> table::get_all_records_as_child(int foreign_key_index, std::vector< value_expression > &expression_list) 235 | { 236 | unsigned int i; 237 | std::vector< main_node *> child_result, result, parent_list; 238 | 239 | //Retrieving all the records in the parent table that satisfies given conditions 240 | parent_list = foreign_key[foreign_key_index].first->select_via_and(expression_list); 241 | 242 | for(i = 0; i < parent_list.size(); i++) 243 | { 244 | //Fetching all child records that satisfies the given condition 245 | child_result = get_records_as_child(foreign_key_index, parent_list[i]); 246 | 247 | //Taking union of these results - We can use vectors because no overlapping 248 | result.insert(result.end(), child_result.begin(), child_result.end()); 249 | } 250 | 251 | return result; 252 | } 253 | 254 | //Function to join via and 255 | std::vector< main_node * > table::join_via_and(int foreign_key_index, std::vector< value_expression > &expression_list) 256 | { 257 | unsigned int i; 258 | std::vector< value_expression > parent, child; 259 | std::vector< main_node *> parent_result, result; 260 | 261 | for(i = 0; i < expression_list.size(); i++) 262 | { 263 | if(expression_list[i].table) child.push_back(expression_list[i]); 264 | else parent.push_back(expression_list[i]); 265 | } 266 | 267 | 268 | if(parent.size() == 0) return select_via_and(child); 269 | if(child.size() == 0) return get_all_records_as_child(foreign_key_index, parent); 270 | 271 | parent_result = get_all_records_as_child(foreign_key_index, parent); 272 | 273 | for(i = 0; i < parent_result.size(); i++) 274 | { 275 | if(compare_record(parent_result[i], child)) 276 | { 277 | result.push_back(parent_result[i]); 278 | } 279 | } 280 | 281 | return result; 282 | } 283 | 284 | std::set< main_node *> table::join(int foreign_key_index, std::vector< std::vector< value_expression > > &expression_vec) 285 | { 286 | /* 287 | * This function joins the current table with it's parent table 288 | * It accepts vector of vector for expression 289 | * Outer Vector for OR and Inner Vector for AND 290 | */ 291 | 292 | unsigned int i; 293 | main_node *head; 294 | std::set< main_node * > result; 295 | std::vector< main_node *> temp_result; 296 | 297 | for(i = 0; i < expression_vec.size(); i++) 298 | { 299 | //temporary result selected via AND 300 | temp_result = join_via_and(foreign_key_index, expression_vec[i]); 301 | 302 | //Taking UNION of current result with previous result 303 | result.insert(temp_result.begin(), temp_result.end()); 304 | } 305 | 306 | return result; 307 | } 308 | 309 | #endif // SELECT_INCLUDED 310 | -------------------------------------------------------------------------------- /src/table.h: -------------------------------------------------------------------------------- 1 | #ifndef TABLE_INCLUDED 2 | #define TABLE_INCLUDED 1 3 | 4 | class domain; 5 | class foreign_node; 6 | class main_node; 7 | class domain; 8 | 9 | #include "domain.h" 10 | 11 | bool compare_values(std::string &left, std::string &right, int op, int data_type) 12 | { 13 | /* 14 | Function to compare 2 strings using given operator and data type and returns final result 15 | 0 -> = 16 | 1 -> <= 17 | 2 -> >= 18 | 3 -> != 19 | 4 -> > 20 | 5 -> < 21 | */ 22 | 23 | if(data_type == domain::INTEGER) 24 | { 25 | int l, r; 26 | sscanf(left.c_str(), "%d", &l); 27 | sscanf(right.c_str(), "%d", &r); 28 | 29 | if(l == r && op < 3) return true; // Values Equal 30 | else if(l < r && (op == 1 || op == 3 || op == 5)) return true; //Values Less Than 31 | else if(l > r && (op == 2 || op == 3 || op == 4)) return true; //Values Greater Than 32 | else return false; 33 | } 34 | else if(data_type == domain::FLOAT) 35 | { 36 | float l, r; 37 | sscanf(left.c_str(), "%f", &l); 38 | sscanf(right.c_str(), "%f", &r); 39 | 40 | if(l == r && op < 3) return true; // Values Equal 41 | else if(l < r && (op == 1 || op == 3 || op == 5)) return true; //Values Less Than 42 | else if(l > r && (op == 2 || op == 3 || op == 4)) return true; //Values Greater Than 43 | else return false; 44 | } 45 | else if(data_type == domain::STRING) 46 | { 47 | int res = left.compare(right); 48 | 49 | if(res == 0 && op < 3) return true; //Values Equal 50 | else if(res < 0 && (op == 1 || op == 3 || op == 5)) return true; //Values Less Than 51 | else if(res > 0 && (op == 2 || op == 3 || op == 4)) return true; //Values Greater Than 52 | else return false; 53 | } 54 | else 55 | { 56 | printf("Wrong Data Type Passed to Compare Function\nAborting\n"); 57 | fflush(stdout); 58 | abort(); 59 | } 60 | } 61 | 62 | struct value_expression{ 63 | 64 | /* 65 | * table signifies if it's parent table or child table expression 66 | * True = Child 67 | * False = Parent 68 | */ 69 | bool table; 70 | int attribute; 71 | int op; 72 | std::string value; 73 | 74 | value_expression() 75 | { 76 | table = true; 77 | } 78 | }; 79 | 80 | class table { 81 | 82 | private: 83 | std::string name; //Name of the Table 84 | main_node *head; //Head to the main list of the table 85 | int record_count; //Number of records 86 | size_t total_size; 87 | std::vector< domain * > normal; 88 | std::vector< std::string > attribute_names; 89 | std::vector< int > index_in_domain; 90 | std::vector< int > primary_keys; 91 | std::vector< std::pair< table *, std::vector< int > > > foreign_key; 92 | 93 | public: 94 | //Constructor that creates a table with given name 95 | table(std::string table_name, int attribute_count) 96 | { 97 | name = table_name; 98 | record_count = 0; 99 | head = NULL; 100 | normal.resize(attribute_count); 101 | attribute_names.resize(attribute_count); 102 | index_in_domain.resize(attribute_count); 103 | } 104 | 105 | int get_primary_key_size() 106 | { 107 | return primary_keys.size(); 108 | } 109 | 110 | void add_foreign_key(table *temp_table, std::vector< int > &fk_list) 111 | { 112 | std::pair
> temp_pair = std::make_pair(temp_table, fk_list); 113 | foreign_key.push_back(temp_pair); 114 | } 115 | 116 | //Function to retrive attribute count in the table 117 | int get_attribute_count() 118 | { 119 | return normal.size(); 120 | } 121 | 122 | //Function to set main node head 123 | void set_main_node_head(main_node *new_head) 124 | { 125 | head = new_head; 126 | } 127 | //Function that adds an attribute to the table 128 | void add_attribute(int type, std::string name, int index) 129 | { 130 | int tab_index; 131 | domain *temp_domain; 132 | temp_domain = new domain(type); 133 | tab_index = temp_domain->insert_table_pointer(this); 134 | normal[index] = temp_domain; 135 | attribute_names[index] = name; 136 | index_in_domain[index] = tab_index; 137 | } 138 | 139 | //Function to link to already existing domain 140 | void add_foreign_domain(std::string name, domain *dom, unsigned int index) 141 | { 142 | unsigned int tab_index; 143 | 144 | tab_index = dom->insert_table_pointer(this); 145 | normal[index] = dom; 146 | attribute_names[index] = name; 147 | index_in_domain[index] = tab_index; 148 | } 149 | 150 | //Function to return the index in primary_key list 151 | int get_primary_attribute(unsigned int i) 152 | { 153 | if(i > primary_keys.size()) 154 | { 155 | printf("Wrong Primary Key Attribute Index Requested!\nAborting!!"); 156 | fflush(stdout); 157 | abort(); 158 | } 159 | return primary_keys[i]; 160 | } 161 | 162 | //Funtion to return the domain from primary key list 163 | domain *get_domain(unsigned int i) 164 | { 165 | return normal[primary_keys[i]]; 166 | } 167 | 168 | //Function to find all the main_nodes with a certain attribute value 169 | std::vector< main_node * > *get_records_with_val(unsigned int attribute_index, std::string &value) 170 | { 171 | return normal[attribute_index]->get_main_nodes(value, index_in_domain[attribute_index]); 172 | } 173 | 174 | //Function to add primary key to the table 175 | void add_primary_key(unsigned int attribute_index) 176 | { 177 | if (attribute_index >= normal.size()) 178 | { 179 | printf("%d attribute doesn't exist !!\nFailed to add primary key !!\nAborting", attribute_index); 180 | fflush(stdout); 181 | abort(); 182 | } 183 | 184 | primary_keys.push_back(attribute_index); 185 | return; 186 | } 187 | 188 | //Function to return a main node having the given primary key 189 | main_node* check_for_primary(std::vector< std::string > &values) 190 | { 191 | unsigned int i, j, col_index, node_count = INT_MAX, index = INT_MAX; 192 | std::vector< main_node * > *fetch_nodes, min_nodes; 193 | 194 | for(i = 0; i < primary_keys.size(); i++) 195 | { 196 | col_index = primary_keys[i]; 197 | fetch_nodes = normal[col_index]->get_main_nodes(values[i], index_in_domain[col_index]); 198 | 199 | if(!fetch_nodes || !fetch_nodes->size()) 200 | { 201 | return NULL; 202 | } 203 | 204 | if(node_count > fetch_nodes->size()) 205 | { 206 | node_count = fetch_nodes->size(); 207 | min_nodes = *fetch_nodes; 208 | index = i; 209 | } 210 | 211 | } 212 | 213 | for(i = 0; i < min_nodes.size(); i++) 214 | { 215 | for(j = 0; j < primary_keys.size(); j++) 216 | { 217 | col_index = primary_keys[j]; 218 | if(j != index && values[j].compare(min_nodes[i]->get_attribute_value(col_index)) != 0) 219 | { 220 | break; 221 | } 222 | } 223 | 224 | if(j == primary_keys.size()) 225 | { 226 | return min_nodes[i]; 227 | } 228 | } 229 | 230 | return NULL; 231 | } 232 | 233 | // Function to add foreign key links 234 | int add_foreign_key_links(std::vector< std::string > &values, main_node *new_main_node) 235 | { 236 | std::vector< std::string > temp_values; 237 | table *temp_table; 238 | main_node *temp_main_node; 239 | unsigned int i, j; 240 | 241 | for (i = 0; i < foreign_key.size(); i++) 242 | { 243 | temp_table = foreign_key[i].first; 244 | for (j = 0; j < foreign_key[i].second.size(); j++) 245 | { 246 | temp_values.push_back(values[foreign_key[i].second[j]]); 247 | } 248 | 249 | temp_main_node = temp_table->check_for_primary(temp_values); 250 | if (temp_main_node == NULL) 251 | { 252 | temp_values.clear(); 253 | return 1; 254 | } 255 | new_main_node->add_foreign_key_link(temp_main_node); 256 | temp_values.clear(); 257 | } 258 | return 0; 259 | } 260 | 261 | //Function that adds a new record to table 262 | int add_new_record(std::vector< std::string > &values) 263 | { 264 | std::vector< std::string > prime(primary_keys.size()); 265 | unsigned int i; 266 | 267 | for(i = 0; i < primary_keys.size(); i++) 268 | { 269 | if(!values[primary_keys[i]].empty()) 270 | { 271 | break; 272 | } 273 | } 274 | 275 | if(i == primary_keys.size()) 276 | { 277 | return -1; 278 | } 279 | 280 | for(i = 0; i < primary_keys.size(); i++) 281 | { 282 | prime[i].assign(values[primary_keys[i]]); 283 | } 284 | 285 | if(check_for_primary(prime)) 286 | { 287 | prime.clear(); 288 | return 0; 289 | } 290 | 291 | prime.clear(); 292 | 293 | main_node* new_main = new main_node(); 294 | if (add_foreign_key_links(values, new_main) == 1) 295 | { 296 | new_main->clear(); 297 | delete new_main; 298 | return -2; 299 | } 300 | 301 | size_t node_size; 302 | for(i = 0; i < values.size(); i++) 303 | { 304 | node_size = sizeof(main_node *); 305 | normal[i]->add_get_new_value(values[i], new_main, index_in_domain[i], true, node_size); 306 | total_size += node_size; 307 | } 308 | 309 | new_main->set_next(head); 310 | head = new_main; 311 | total_size += head->get_size(); 312 | record_count++; 313 | return 1; 314 | } 315 | 316 | //Function that compares a particular attribute value of a record and returns result 317 | bool compare_attribute(main_node *record, value_expression expr) 318 | { 319 | std::string attr_val = record->get_attribute_value(expr.attribute); 320 | return compare_values(attr_val, expr.value, expr.op, normal[expr.attribute]->get_data_type()); 321 | } 322 | 323 | //Function to compare all given values of a record with attributes are returns result 324 | bool compare_record(main_node *record, std::vector< value_expression > &expr, int skip) 325 | { 326 | /* 327 | Skip was added to avoid extra string comparison when it is certain that condition in the given 328 | position will evaluate to true. All Logical operatos assumed to be true. Shortcircuiting 329 | expressions also implemented 330 | */ 331 | 332 | unsigned int i; 333 | 334 | for(i = 0; i < expr.size(); i++) 335 | { 336 | if((expr[i].attribute != skip) && (!compare_attribute(record, expr[i]))) 337 | { 338 | return false; 339 | } 340 | } 341 | 342 | return true; 343 | } 344 | 345 | //Overloaded Function to compare all given values with attributes without skipping 346 | bool compare_record(main_node *record, std::vector< value_expression > &expr) 347 | { 348 | return compare_record(record, expr, -1); 349 | } 350 | 351 | void update(std::set< main_node * > &nodes, std::vector< int > &index, std::vector< std::string > &values) 352 | { 353 | std::set< main_node * >::iterator it; 354 | unsigned int j; 355 | attribute_node *old_node; 356 | size_t temp_size; 357 | for(it = nodes.begin(); it != nodes.end(); it++) 358 | { 359 | for(j = 0; j < index.size(); j++) 360 | { 361 | old_node = (*it)->get_attribute_list_index(index[j]); 362 | if(values[j].compare(old_node->get_value())) 363 | { 364 | old_node->delete_edge((*it), index_in_domain[index[j]]); 365 | attribute_node *new_attribute_node = normal[index[j]]->add_get_new_value(values[j], 366 | (*it), index_in_domain[index[j]], false, temp_size); 367 | (*it)->update_attribute(index[j], new_attribute_node); 368 | } 369 | } 370 | } 371 | } 372 | 373 | 374 | void update_all(std::vector< int > &index, std::vector< std::string > &values) 375 | { 376 | unsigned int j; 377 | attribute_node *old_node; 378 | size_t temp_size; 379 | main_node *temp, *temp_main; 380 | 381 | while(head && head->lazy_delete()) 382 | { 383 | temp = head; 384 | head = head->get_next(); 385 | delete temp; 386 | } 387 | 388 | if(head == NULL) return; 389 | 390 | for(j = 0; j < index.size(); j++) 391 | { 392 | old_node = head->get_attribute_list_index(index[j]); 393 | if(values[j].compare(old_node->get_value())) 394 | { 395 | old_node->delete_edge(head, index_in_domain[index[j]]); 396 | attribute_node *new_attribute_node = normal[index[j]]->add_get_new_value(values[j], 397 | head, index_in_domain[index[j]], false, temp_size); 398 | head->update_attribute(index[j], new_attribute_node); 399 | } 400 | } 401 | 402 | temp_main = head; 403 | temp = head->get_next(); 404 | 405 | while(temp) 406 | { 407 | if(temp->lazy_delete()) 408 | { 409 | temp_main->delete_next(); 410 | } 411 | 412 | else 413 | { 414 | for(j = 0; j < index.size(); j++) 415 | { 416 | old_node = temp->get_attribute_list_index(index[j]); 417 | if(values[j].compare(old_node->get_value())) 418 | { 419 | old_node->delete_edge(temp, index_in_domain[index[j]]); 420 | attribute_node *new_attribute_node = normal[index[j]]->add_get_new_value(values[j], 421 | temp, index_in_domain[index[j]], false, temp_size); 422 | temp->update_attribute(index[j], new_attribute_node); 423 | } 424 | } 425 | temp_main = temp; 426 | } 427 | temp = temp_main->get_next(); 428 | } 429 | 430 | } 431 | 432 | void del(std::set< main_node * > &nodes) 433 | { 434 | std::set< main_node * >::iterator it; 435 | unsigned int i; 436 | std::vector< attribute_node * > *old_nodes; 437 | for(it = nodes.begin(); it != nodes.end(); it++) 438 | { 439 | old_nodes = (*it)->get_attribute_list(); 440 | for(i = 0; i < old_nodes->size(); i++) 441 | { 442 | (*old_nodes)[i]->delete_edge((*it), index_in_domain[i]); 443 | } 444 | 445 | (*it)->del_node(); 446 | 447 | } 448 | 449 | } 450 | 451 | void delete_all() 452 | { 453 | unsigned int i; 454 | std::vector< attribute_node * > *old_nodes; 455 | main_node *temp; 456 | temp = head; 457 | while(head) 458 | { 459 | if(head->lazy_delete() == false) 460 | { 461 | old_nodes = head->get_attribute_list(); 462 | for(i = 0; i < old_nodes->size(); i++) 463 | { 464 | (*old_nodes)[i]->delete_edge(head, index_in_domain[i]); 465 | } 466 | head->del_node(); 467 | } 468 | temp = head; 469 | head = head->get_next(); 470 | delete temp; 471 | } 472 | 473 | } 474 | 475 | std::string get_attribute_name(unsigned int attribute_index) 476 | { 477 | if(attribute_index >= attribute_names.size()) 478 | { 479 | printf("Attribute Index %d do not exist!!\nAborting!!", attribute_index); 480 | fflush(stdout); 481 | abort(); 482 | } 483 | 484 | return attribute_names[attribute_index]; 485 | } 486 | 487 | //Function to find table's name 488 | std::string get_table_name() 489 | { 490 | return name; 491 | } 492 | 493 | //Function get the domain connect at a corresponding index 494 | domain *get_normal_index(unsigned int normal_index) 495 | { 496 | if (normal_index >= normal.size()) 497 | { 498 | printf("%d Normal Index do not exist !!\nAborting!!", normal_index); 499 | fflush(stdout); 500 | abort(); 501 | } 502 | 503 | return normal[normal_index]; 504 | } 505 | 506 | //Function to get head of main_node list for iteration 507 | main_node *get_main_node_head() 508 | { 509 | return head; 510 | } 511 | 512 | //Function to return the number of parent tables 513 | int get_foreign_key_count() 514 | { 515 | return foreign_key.size(); 516 | } 517 | 518 | //Function to get parent table of a foreign_key 519 | table *get_parent_table(unsigned int foreign_key_index) 520 | { 521 | if(foreign_key_index > foreign_key.size()) 522 | { 523 | printf("%d foreign_key do not exist !!\nAborting!!", foreign_key_index); 524 | fflush(stdout); 525 | abort(); 526 | } 527 | 528 | return foreign_key[foreign_key_index].first; 529 | } 530 | 531 | // Function to check whether the table has a parent table named "parent_name" or not 532 | // Returns the foreign_key_index if it exists else -1 533 | int check_parent_name(std::string parent_name) 534 | { 535 | int i; 536 | std::transform(parent_name.begin(), parent_name.end(), parent_name.begin(), toupper); 537 | for (i = 0; i < foreign_key.size(); i++) 538 | { 539 | if (foreign_key[i].first->get_table_name().compare(parent_name) == 0) 540 | { 541 | printf("Parent = %s\n", foreign_key[i].first->get_table_name().c_str()); 542 | return i; 543 | } 544 | } 545 | return -1; 546 | } 547 | 548 | // Function to check whether the table has a column named "col_name" or not 549 | // Returns the column number if it exists else -1 550 | int check_column_name(std::string column_name) 551 | { 552 | int i; 553 | std::transform(column_name.begin(), column_name.end(), column_name.begin(), toupper); 554 | for (i = 0; i < attribute_names.size(); i++) 555 | { 556 | if (attribute_names[i].compare(column_name) == 0) 557 | { 558 | printf("Column = %s\n", attribute_names[i].c_str()); 559 | return i; 560 | } 561 | } 562 | return -1; 563 | } 564 | 565 | //Function to deallocate memory occupied by the table 566 | void clear() 567 | { 568 | unsigned int i, j; 569 | bool *check = new bool[attribute_names.size()]; 570 | 571 | for(i = 0; i < attribute_names.size(); i++) 572 | { 573 | check[i] = false; 574 | } 575 | 576 | for(i = 0; i < foreign_key.size(); i++) 577 | { 578 | for(j = 0; j < foreign_key[i].second.size(); j++) 579 | check[foreign_key[i].second[j]] = true; 580 | } 581 | 582 | name.clear(); 583 | for(i = 0; i < normal.size(); i++) 584 | { 585 | if(!check[i]) 586 | { 587 | normal[i]->clear(); 588 | delete normal[i]; 589 | } 590 | } 591 | delete[] check; 592 | normal.clear(); 593 | primary_keys.clear(); 594 | 595 | main_node *temp ; 596 | 597 | while(head != NULL) 598 | { 599 | temp = head->get_next(); 600 | head->clear(); 601 | delete head; 602 | head = temp; 603 | } 604 | attribute_names.clear(); 605 | 606 | for (i = 0; i < foreign_key.size(); i++) 607 | { 608 | foreign_key[i].second.clear(); 609 | } 610 | foreign_key.clear(); 611 | } 612 | 613 | void add_to_size(size_t add) 614 | { 615 | total_size += add; 616 | } 617 | 618 | size_t get_size() 619 | { 620 | return total_size; 621 | } 622 | 623 | int get_num_records() 624 | { 625 | return record_count; 626 | } 627 | 628 | //Function Definition in table 629 | std::vector< main_node * > select_via_and(std::vector< value_expression > &expression_list); 630 | std::set< main_node * > select_single_table(std::vector< std::vector< value_expression > > &expression_vec); 631 | std::vector< main_node *> get_records_as_child(int foreign_key_index, main_node *parent_record); 632 | std::vector< main_node *> get_all_records_as_child(int foreign_key_index, std::vector< value_expression > &expression_list); 633 | std::vector< main_node * > join_via_and(int foreign_key_index, std::vector< value_expression > &expression_list); 634 | std::set< main_node *> join(int foreign_key_index, std::vector< std::vector< value_expression > > &expression_vec); 635 | void select_all(std::vector< int > &col_list); 636 | }; 637 | 638 | #endif // TABLE_INCLUDED 639 | -------------------------------------------------------------------------------- /src/test.h: -------------------------------------------------------------------------------- 1 | void create_dept(database *db) 2 | { 3 | table *temp_table; 4 | 5 | temp_table = new table(std::string("DEPARTMENT"), 3); 6 | temp_table->add_attribute(1, "ID", 0); 7 | temp_table->add_attribute(2, "NAME", 1); 8 | temp_table->add_attribute(2, "LOCATION", 2); 9 | temp_table->add_primary_key(0); 10 | db->add_table(temp_table); 11 | } 12 | 13 | void create_emp(database *db) 14 | { 15 | table *temp_table, *foreign_table; 16 | std::vector< int > fk_list; 17 | temp_table = new table(std::string("EMPLOYEE"), 6); 18 | temp_table->add_attribute(1, "ID", 0); 19 | temp_table->add_attribute(2, "NAME", 1); 20 | temp_table->add_attribute(2, "ADDRESS", 2); 21 | temp_table->add_attribute(3, "SALARY", 3); 22 | temp_table->add_attribute(2, "SEX", 4); 23 | temp_table->add_primary_key(0); 24 | 25 | foreign_table = db->get_table(0); 26 | temp_table->add_foreign_domain("DEPT_ID", foreign_table->get_domain(0), 5); 27 | fk_list.push_back(5); 28 | temp_table->add_foreign_key(foreign_table, fk_list); 29 | db->add_table(temp_table); 30 | } 31 | 32 | void insert_dept(database *db) 33 | { 34 | srand(time(NULL)); 35 | int i, j, success, num_records, unique_rec_count, attribute_len, failed = 0, start, stop; 36 | double result_time = 0; 37 | num_records = 20; 38 | unique_rec_count = 15; 39 | attribute_len = 30; 40 | 41 | table *temp_table; 42 | char *str = new char[num_records + 1]; 43 | char *s = new char[attribute_len + 1]; 44 | 45 | temp_table = db->get_table(0); 46 | std::vector< std::string > values(temp_table->get_attribute_count()); 47 | std::vector< std::string > unique_rec(unique_rec_count); 48 | 49 | for(i = 0; i < unique_rec_count; i++) 50 | { 51 | for(j = 0; j < attribute_len; j++) 52 | { 53 | s[j] = 'a' + (rand() % 26); 54 | } 55 | s[j] = '\0'; 56 | 57 | unique_rec[i].assign(s); 58 | } 59 | 60 | for(i = 1; i <= num_records; i++) 61 | { 62 | sprintf(str, "%d", i); 63 | values[0].assign(str); 64 | values[1] = unique_rec[rand() % unique_rec_count]; 65 | values[2] = unique_rec[rand() % unique_rec_count]; 66 | 67 | start = clock(); 68 | success = temp_table->add_new_record(values); 69 | stop = clock(); 70 | result_time += stop - start; 71 | 72 | if(success != 1) 73 | { 74 | failed++; 75 | } 76 | } 77 | 78 | if(failed) 79 | { 80 | printf("Failed : %d\n", failed); 81 | } 82 | 83 | printf("\nInsert Time for dept :%lf\n", result_time/double(CLOCKS_PER_SEC)); 84 | delete[] str; 85 | delete[] s; 86 | values.clear(); 87 | unique_rec.clear(); 88 | } 89 | 90 | void insert_emp(database *db) 91 | { 92 | srand(time(NULL)); 93 | int i, j, success, num_records, unique_rec_count, attribute_len, failed = 0, start, stop, max_sal; 94 | float sal; 95 | double result_time = 0; 96 | max_sal = 1000000; 97 | num_records = 100; 98 | unique_rec_count = 50; 99 | attribute_len = 20; 100 | 101 | table *temp_table; 102 | char *str = new char[num_records + 1]; 103 | char *s = new char[attribute_len + 1]; 104 | 105 | temp_table = db->get_table(1); 106 | std::vector< std::string > values(temp_table->get_attribute_count()); 107 | std::vector< std::string > unique_rec(unique_rec_count); 108 | 109 | for(i = 0; i < unique_rec_count; i++) 110 | { 111 | for(j = 0; j < attribute_len; j++) 112 | { 113 | s[j] = 'a' + (rand() % 26); 114 | } 115 | s[j] = '\0'; 116 | 117 | unique_rec[i].assign(s); 118 | } 119 | 120 | for(i = 1; i <= num_records; i++) 121 | { 122 | sprintf(str, "%d", i); 123 | values[0].assign(str); 124 | values[1] = unique_rec[rand() % unique_rec_count]; 125 | values[2] = unique_rec[rand() % unique_rec_count]; 126 | sal = (rand()/(float)RAND_MAX) * max_sal; 127 | sprintf(s, "%f", sal); 128 | values[3].assign(s); 129 | if(rand() % 2) 130 | { 131 | values[4].assign("Male"); 132 | } 133 | else 134 | { 135 | values[4].assign("Female"); 136 | } 137 | j = (rand() % 20) + 1; 138 | sprintf(s, "%d", j); 139 | values[5].assign(s); 140 | start = clock(); 141 | success = temp_table->add_new_record(values); 142 | stop = clock(); 143 | result_time += stop - start; 144 | 145 | if(success != 1) 146 | { 147 | failed++; 148 | } 149 | } 150 | 151 | if(failed) 152 | { 153 | printf("Failed : %d\n", failed); 154 | } 155 | 156 | printf("\nInsert Time for employee :%lf\n", result_time/double(CLOCKS_PER_SEC)); 157 | delete[] str; 158 | delete[] s; 159 | values.clear(); 160 | unique_rec.clear(); 161 | } 162 | -------------------------------------------------------------------------------- /src/test_scripts/insert.php: -------------------------------------------------------------------------------- 1 | get_child(index); 73 | if(!temp) 74 | { 75 | if(!exists) 76 | { 77 | return insert_node(node_crawl, key, level, length, num_tables); 78 | } 79 | return NULL; 80 | } 81 | node_crawl = temp; 82 | } 83 | 84 | attribute_node *node = node_crawl->get_node(); 85 | 86 | if(!node && !exists) 87 | { 88 | node = new attribute_node(key, num_tables); 89 | node_crawl->set_node(node); 90 | } 91 | else 92 | { 93 | exists = true; 94 | } 95 | 96 | return node; 97 | 98 | } 99 | 100 | attribute_node *insert_node(trie_node *node_crawl, std::string &key, int level, int length, int num_tables) 101 | { 102 | int index = key[level]; 103 | trie_node *temp; 104 | 105 | while(level <= length) 106 | { 107 | temp = new trie_node(); 108 | node_crawl->set_child(index, temp); 109 | node_crawl = temp; 110 | node_crawl->set_val(key[level++]); 111 | index = key[level]; 112 | } 113 | 114 | attribute_node *node; 115 | node = new attribute_node(key, num_tables); 116 | node_crawl->set_node(node); 117 | return node; 118 | 119 | } 120 | 121 | void clear() 122 | { 123 | clear(root); 124 | } 125 | 126 | void clear(trie_node *root) 127 | { 128 | if(root != NULL) 129 | { 130 | for(int i = 0; i < MAX_SIZE; i++) 131 | { 132 | clear(root->get_child(i)); 133 | } 134 | 135 | delete root; 136 | } 137 | } 138 | 139 | }; 140 | 141 | #endif //TRIE_INCLUDED 142 | 143 | --------------------------------------------------------------------------------