Database System Project Submission

Page 1

CS 5300 - database systems Hadi Ataei Professor Ali Hurson January 15, 2015

1


Introduction: This project, as the semester’s project for the Data Base Systems course pursues the goal of writing a code in C++ which would take in an SQL Query, translates it into its equivalent relational algebra, generate a Query tree based on that, and finally, transforms the Query tree by performing several optimization heuristics which aims at reducing the cost of the query. Procedure: For parsing the Query, the code uses key words and symbols to distinguish between different parts of the query. For instance, the code read the query line by line. In the next step, it looks for the (tab). It reads in whatever is before tab into ’keyv’ variable. Based on the value of the keyv it know which clause the ’line’ is reading in. If keyv is SELECT then the code would search the line for a ’.’ (dot) and if there is one, it will read the relation alias or name and the attribute into their appropriate variable. The key characters in FROM clause which would be used in parsing would be AS and ’,’ (comma). AS would determine that there is an alias used for each relation, and a comma would indicate the introduction of a new relation into the natural join operation. The key characters in WHERE would be ’=’ and ”AND” and ’.’ (dot). For instance AND is used to take apart the expressions and so on. For the next three processes, the code distinguishes between four types of query. The first type is a simple query, which does not have neither a nested query nor a two-part query with an intermediate operation. The second type would be a query which has a nested query and no intermediate operation, third type would be a query with an intermediate operation and not nested query, and the fourth type would be a query with both a nested query and an intermediate operation. There four different functions called nodifyCase1(), nodifyCase2(), nodifyCase3() and nodifyCase4() which correspond to each type respectively. Each of these functions creates both a relational algebra and the query tree. The last step would be to optimize the query tree. There are three different functions used for this purpose. The first is expediteBowtie(GravphViz& graph) which takes in the graph, and looks at the expressions within a node that has the join operation. If both relations on both sides of an expression are below to one sides of the node, it will move the expression down that direction. The next function used here is expediteSelect(SuperQuery& input, GraphViz& graph) which will take in the graph, looks at each node with a join operation. Within that node, if there is an expression with a constant value, it will look for a node below the aforementioned node which contains the relation on the left side of that expression. Then, the function will create a new node right above that relation node, with the operation 2


SELECT and the same expression as the one a constant value. The last optimization function would be expediteProject(GraphViz& graph) which would take in the graph, and find the nodes with relations that participate in the join operation. Then it will find the nodes above it, and determines which attribute from that relation are being used above that node. In the last step, it will create a node with a PROJECT operation and the attributes which have been found in the previous step.

Π(S.sname) (Sailors AS S ⨝(S.sid=R.sid AND R.bid=103) (Reserves AS R)

Figure 1: Query 1: Relational Algebra

Π (S.sname)

⨝ (S.sid=R.sid )(R.bid=103)

(Sailors AS S)

(Reserves AS R)

Figure 2: Query 1: Query tree 3


Π (S.sname)

⨝ (S.sid=R.sid )

Π (sname, sid)

σ (R.bid=103)

(Sailors AS S)

Π (sid , bid)

(Reserves AS R)

Figure 3: Query 1: Query tree after optimization

4


Π(S.sname) (Sailors AS S ⨝(S.sid=R.sid AND R.bid=B.bid AND B.color='red') (Reseves AS R⨝(Boats AS B))

Figure 4: Query2: Relational Algebra

Π (S.sname)

⨝ (S.sid=R.sid )(R.bid=B.bid )(B.color='red')

(Sailors AS S)

(Reseves AS R)

(Boats AS B)

Figure 5: Query2: Query tree

5


Π (S.sname)

⨝ (S.sid=R.sid )

Π (sid , bid)

σ (B.color='red')

(Reseves AS R)

Π (bid , color)

Π (sname, sid)

(Sailors AS S)

(Boats AS B)

Figure 6: Query2: Query tree after optimization

6


7 Figure 7: Query3: Relational Algebra

Π(Fname, Lname, Address) (EMPLOYEE ⨝(employee.Dno=Department.Dnumber AND Department.Dname='research') (Department)


Π (Fname, Lname, Address)

⨝ (employee.Dno=Department.Dnumber )(Department.Dname='research')

(EMPLOYEE)

(Department)

Figure 8: Query3: Query tree

8


Π (Fname, Lname, Address)

⨝ (employee.Dno=Department.Dnumber )

Π

(EMPLOYEE)

σ (Department.Dname='research')

Π (Dnumber , Dname)

(Department)

Figure 9: Query3: Query tree after optimization

9


10

Figure 10: Query4: Relational Algebra

(Π(sname) (Sailors ⨝(Sailors.sid=Reserves.sid AND Reserves.bid=Boats.bid AND Boats.color='red') (Boats⨝(Reserves))))∪ (Π(sname) (Sailors ⨝(Sailors.sid=Reserves.sid AND Reserves.bid=Boats.bid AND Boats.color='green') (Boats⨝(Reserves)))


11

Figure 11: Query4: Query tree (Boats)

(Sailors) ⨝

(Reserves)

⨝ (Sailors.sid=Reserves.sid )(Reserves.bid=Boats.bid )(Boats.color='red')

Π (sname)

(Boats)

(Sailors)

(Reserves)

⨝ (Sailors.sid=Reserves.sid )(Reserves.bid=Boats.bid )(Boats.color='green')

Π (sname)


(Sailors)

Π (sid, sname)

12

Figure 12: Query4: Query tree after optimization (Reserves)

Π (bid , color)

(Boats)

Π (sid , bid)

σ (Boats.color='red')

⨝ (Reserves.bid=Boats.bid )

⨝ (Sailors.sid=Reserves.sid )

Π (sname)

(Sailors)

Π (sid, sname)

⨝ (Sailors.sid=Reserves.sid )

Π (sname)

(Boats)

Π (bid , color)

σ (Boats.color='green')

⨝ (Reserves.bid=Boats.bid )

(Reserves)

Π (sid , bid)


13

Figure 13: Query5: Relational Algebra

Π(S.sname) (Sailors AS S ⨝(R.sid=S.sid AND R.bid=100 AND S.rating>5 AND R.day='8/9/09') (Reserves AS R)


14

Figure 14: Query5: Query tree

(Sailors AS S)

(Reserves AS R)

⨝ (R.sid=S.sid )(R.bid=100 )(S.rating>5 )(R.day='8/9/09')

Π (S.sname)


Π (S.sname)

⨝ (R.sid=S.sid )

σ (S.rating>5 )

σ (R.bid=100 )

Π (sname, sid , rating)

σ (R.day='8/9/09')

(Sailors AS S)

Π (sid, bid, day)

(Reserves AS R)

Figure 15: Query5: Query tree after optimization

15


16

Figure 16: Query6: Relational Algebra

(Π(sname) (Sailors ⨝(Sailors.sid=Reserves.sid AND Reserves.bid=Boats.bid AND Boats.color='red') (Boats⨝(Reserves))))⋂ (Π(sname) (Sailors ⨝(Sailors.sid=Reserves.sid AND Reserves.bid=Boats.bid AND Boats.color='green') (Boats⨝(Reserves)))


17

Figure 17: Query6: Query tree (Boats)

(Sailors) ⨝

(Reserves)

⨝ (Sailors.sid=Reserves.sid )(Reserves.bid=Boats.bid )(Boats.color='red')

Π (sname)

(Boats)

(Sailors)

(Reserves)

⨝ (Sailors.sid=Reserves.sid )(Reserves.bid=Boats.bid )(Boats.color='green')

Π (sname)


18

Figure 18: Query6: Query tree after optimization

(Sailors)

Π (sid, sname)

(Reserves)

Π (bid , color)

(Boats)

Π (sid , bid)

σ (Boats.color='red')

⨝ (Reserves.bid=Boats.bid )

⨝ (Sailors.sid=Reserves.sid )

Π (sname)

(Sailors)

Π (sid, sname)

⨝ (Sailors.sid=Reserves.sid )

Π (sname)

(Boats)

Π (bid , color)

σ (Boats.color='green')

⨝ (Reserves.bid=Boats.bid )

(Reserves)

Π (sid , bid)


19

(Π(S.sid) (Sailors AS S ⨝(S.sid=R.sid AND R.bid=B.bid AND B.color='red') (Reserves AS R⨝(Boats AS B))))- (Π(S2.sid) (Sailors AS S2 ⨝(S2.sid=R2.sid AND R2.bid=B2.bid AND B2.color='green') (Reserves AS R2⨝(Boats AS B2)))


20

Figure 20: Query7: Query tree

(Reserves AS R)

(Sailors AS S)

(Boats AS B)

⨝ (S.sid=R.sid )(R.bid=B.bid )(B.color='red')

Π (S.sid)

-

(Reserves AS R2)

(Sailors AS S2)

(Boats AS B2)

⨝ (S2.sid=R2.sid )(R2.bid=B2.bid )(B2.color='green')

Π (S2.sid)


Figure 21: Query7: Query tree after optimization

21

(Sailors AS S)

Π (sid)

Π (bid , color)

(Reserves AS R)

(Boats AS B)

σ (B.color='red')

Π (sid , bid)

⨝ (R.bid=B.bid )

⨝ (S.sid=R.sid )

Π (S.sid)

-

(Sailors AS S2)

Π (sid)

⨝ (S2.sid=R2.sid )

Π (S2.sid)

(Reserves AS R2)

Π (sid , bid)

⨝ (R2.bid=B2.bid )

(Boats AS B2)

Π (bid , color)

σ (B2.color='green')


22 Figure 22: Query8: Relational Algebra

(Π(S.sname) (Sailors AS S ⨝(S.sid=R.sid) ( Π( R.sid( Reserve AS R( σ( R.bid=103)))))))


Π (S.sname)

⨝ (S.sid=R.sid)

(Sailors AS S)

Π (R.sid)

σ (R.bid=103)

(Reserve AS R)

Figure 23: Query8: Query tree

23


Π (S.sname)

⨝ (S.sid=R.sid)

Π (sname, sid)

Π (R.sid)

(Sailors AS S)

σ (R.bid=103)

Π (bid, sid)

(Reserve AS R)

Figure 24: Query8: Query tree after optimization

24


25

Figure 25: Query9: Relational Algebra

Π(S.sname) (Sailors AS S ⨝(S.sid=R.sid) ( (Π(R.sid) (Reserves AS R ⨝(R.bid=B.bid AND B.color='red') (Boats AS B)))⋂ (Π(R2.sid) (Reserves AS R2 ⨝(R2.bid=B2.bid AND B2.color='green') (Boats AS B2))


Figure 26: Query9: Query tree

26 (Reserves AS R)

(Boats AS B)

⨝ (R.bid=B.bid )(B.color='red')

Π (R.sid)

(Sailors AS S) ⋂

⨝ (S.sid=R.sid)

Π (S.sname)

(Reserves AS R2)

(Boats AS B2)

⨝ (R2.bid=B2.bid )(B2.color='green')

Π (R2.sid)


Figure 27: Query9: Query tree after optimization

27

Π (R.sid)

(Sailors AS S)

Π (bid , color)

(Reserves AS R)

(Boats AS B)

σ (B.color='red')

Π (bid, sid)

⨝ (R.bid=B.bid )

Π (sname, sid)

⨝ (S.sid=R.sid)

Π (S.sname)

(Reserves AS R2)

Π (bid, sid)

⨝ (R2.bid=B2.bid )

Π (R2.sid)

(Boats AS B2)

Π (bid , color)

σ (B2.color='green')


main.cpp

// // // // // // // //

1/15/15, 3:29 AM

DataBase Systems Project: CS 5300 Missouri University of Science and Technology Professor: Dr. Ali Hurson Created by Hadi on 12/21/14. Copyright (c) 2014 Hadi. All rights reserved.

Purpose of the project: This code reads in a query in a text format. Generates a Query tree and performs several optimization processes on the query tree and then generates an optimized query tree. #include "Header.h" #include <ctime> #include <iostream> #include <cstdlib> #include <fstream> #include <string> using namespace std; int main() { SuperQuery input; string keyv, line; ofstream algebraicRelation; ifstream in; ofstream outFile, optFile; GraphViz graph; initiate(keyv, line, in, outFile, optFile, algebraicRelation);//Initiate all the variables. ScanQuery(input, in, keyv, line);// Scans the the query with the name of the file which was read in in the previous step. generateNode(input, graph, algebraicRelation);// It generates the node inside the 'graph' file. createMiddlePart(graph);//It creates the middle part for each node. generateTree(graph, outFile);// It generates the query tree before optimization. createDownSet(graph);// Creates the node number set for each node. createUpSet(graph);// Creates the node number set for the nodes above each node. expediteBowTie(graph);// For those condition expression that be moved down to either left or right. createMiddlePart(graph);// Updates the middle part. (needs to be performed every time. expediteSelect(input, graph);//This is working correctly. Dont touch it. jan 8. 2:08 AM. createMiddlePart(graph);// Repeating this function after each change in 'graph' file. expediteProject(graph);// For each relation, a PROJECT operation is performed on those attributes that will be used, and the rest of the attributes will be ignored in calculations. Page 1 of 2


main.cpp

1/15/15, 3:29 AM

createMiddlePart(graph);// Repeating this function after each change in 'graph' file. generateTree(graph, optFile);// Creates the .dot file for the optimized query tree. in.close(); outFile.close(); optFile.close(); algebraicRelation.close(); return 0; }

Page 2 of 2


Header.h

1/15/15, 3:30 AM

// // // // // // // //

DataBase Systems Project: CS 5300 Missouri University of Science and Technology Professor: Dr. Ali Hurson Created by Hadi on 12/21/14. Copyright (c) 2014 Hadi. All rights reserved. This file includes all the class and struct definitions and function declarations.

#ifndef Header_h #define Header_h #include <iostream> #include <string> #include <fstream>

using namespace std; /*

Relation struct to represent the relation, whenever its actuall name is used or its alias is used. It has a name, member, alias, whether a constant is used. Also overloading operator.*/

struct Relation { string string bool

m_name=""; m_alias=""; m_constant = false;

Relation operator = (const Relation & source);// Overloading the "=" operator for the Relation. bool operator == (const Relation & source); }; /* Side struct is defined to represent one side of an expression in a WHERE clause. Each side, consists of a boolean of whether it is a constant, if not, what relation is used, the attribute used and the m_string which represents one side as a string.*/ struct Side { bool m_useConst= false;//Whether or not there is constant value being compared to. Relation m_relation;//The relation involved in one side of the condition. string m_attribute="";//What is the attribute of the that relation being used in comparison. string m_string = "";//What is the string of the one side of the condition. }; /* Considition struct is actually the expression used in a WHERE clause. It has a left Side and a right Side and a string to represent the two sides and the Page 1 of 8


Header.h

1/15/15, 3:30 AM

operator in one single text as it appears in the query. */ struct Condition { Side m_left; Side m_right; string m_string = "";//This is each condition as a string }; /* Select struct is defined to represent a SELECT clause, which may or may not have an alias, has an attribute, and a relation. */ struct Select { bool string string Relation };

m_useAlias = false; m_attName=""; m_allPhrase=""; m_relation;

/* From struct is to represent FROM clause, which may or may not use an alias, has a number of relations in m_relCount, as many as that would be the number of relations. */ struct From { bool size_t string Relation };

m_useAlias =false; m_relCount=0; m_allPhrase[3]; m_relation[3];

/* Where struct is defined to represent a WHERE clause, which may or may not have a nested query insdie. may or may not use an alias in its expressions, and number of expressions which is in m_noCond. And as many expressions (Conditions) as m_noCond. */ struct Where { string m_allWhere; bool m_nested = false; bool m_useAlias = false; size_t m_noCond = 0 ;//Number of conditions in WHERE. Condition m_condition[10];//Each condition is broken into its different componenets. }; /* Query struct, is to represent a subQuery, which is a portion of the entire query defined by SELECT, FROM and WHERE clauses. */ struct Query { Select m_slct; Where m_whr; From m_frm; Page 2 of 8


Header.h

1/15/15, 3:30 AM

}; /* A superQuery is the entire query dissected into different parts, such as a Query(as above), whether it has two parts, whether it has a nested query. If it is twoPart what is the nature of the intermediate operation (m_twoPartOp).*/ struct SuperQuery { string m_twoPartOp = "";// What is the two-part operation called. string m_twoPartInOP = ""; int m_seq = 0; bool m_twoPart = false; bool m_nested = false; Query m_inQuery[5]; }; // **************************************************************** // **************************** Graphic Structs **************** // **************************************************************** // A struct to reperent each middle Part of the middle part of a node. struct Middle { string m_wholeThing = " ";//The whole thing as a string. string m_attribute[2] = {""};// The attribute used in each part. For a WHERE expression there might be two attributes. Relation m_relation[2];// The relation used in each midPart. Might be two for expressions. }; /* Each Node, which is also a member variable of the GraphViz struct below, has several member variables. Each represent a quality of the node. m_left is the number of the node lower left. m_upLine is the node number of the parent node. */ struct Node { string m_operation= "";//Reperesents the relational algebra used in each node. Middle m_midPart[100];// The mid part, if we have natural join operation, there will be several experessions. Each middle is for each expression. int m_midSeq = 0;//Is the number of midPart[]s that is there for each node. string m_middlePart = " ";// This is to what actually will be entered into the .viz file as the middle part of the node. int m_left = 0;// The node number of the lower left node. int m_right = 0;//Node number of the lower right node. int m_upLine = 0;//Node number of the parent node. int m_downSet[100] = {0};// The vales of the node numbers which are below this node in the tree. The first one in the array is the number of nodes below. int m_upSet[100] = {0};//The node numbers of the node which are above the nodes are in this array bool m_useNode = false;//If the node is used at all in the Query tree. bool m_nodeSet = false;//Pretty the same thing is m_useNode. Page 3 of 8


Header.h

1/15/15, 3:30 AM

Node operator = (const Node & source);//Overloading the operator to set a node equal to another. }; /* GraphViz is a struct to represent a GraphViz file that has several nodes that are interconnected. */ struct GraphViz { int m_noOfNodes = 0;// Node m_nodes[100]; GraphViz operator = (const GraphViz & source);// The operator = is overloaded to work with GraphViz struct. }; // **************************************************************** // **************************** Function headers **************** // **************************************************************** // **************************** /*

Function: It count the number of occurences of a string 'find' in another string 'line'. Input: It takes 'find' and 'string'. OutPut: It outputs an int which is the number of occurences.

*/ int /*

Parse Function Headers **********

count (string line, string find); Function: It scans the inptu query and enters the value for each of SELECT, FROM and WHERE clauses. Input: It takes the input text file, a keyv which is string for key value and and string 'line' to read in every line of the query innto it line by line. 'keyv' is readinto the the key value to recognize what clause is each line about. OutPut: It outputs nothing but changes 'line' and 'keyv' accordingly.

*/ void

ScanQuery(SuperQuery& input, ifstream& in, string& keyv, string& line);

/*

Function: If there is a nested query in WHERE, this format of ScanQuery is used to scan the remainder of the query. Input: The same as ScanQuery. OutPut: The same as Scan Query. */ void ScanNQuery(SuperQuery& input, ifstream& in, string& keyv, string& line); /*

Function: If there is an intermediate operation with a two part query, this format of ScanQuery is used to scan the remainder of the query. Input: The same as Scan Query. OutPut: The same as ScanQuery.

*/ void /*

Scan2Query(SuperQuery& input, ifstream& in, string& keyv, string& line);

Function: It initiates the query input process. It asks what is the input file name and set the output file name. Input: Takes in the input file, the keyv and the line. OutPut: Outputs nothing but, changes the values of keyv and line. Page 4 of 8


Header.h

1/15/15, 3:30 AM

*/ void initiate(string& keyv, string& line, ifstream& in, ofstream& outFile, ofstream& optFile, ofstream& algebraicRelation); /*

Function: Input: OutPut:

*/ void /*

parseSelect(SuperQuery& input, string& line);

Function: If keyv's value is "FROM" then this function is called to parse the FROM clause. Input: It takes in 'line' as a string and 'input'. OutPut: Returns nothing but updates the SuperQuery 'input'.

*/ void /*

readKeyv(string& keyv, string& line);

Function: If keyv's value is SELECT then this function is called which will parses the SELECT caluse and enters the corresponding values. Input: It takes in 'line' as a string and 'input'. OutPut: Returns nothing but updates the SuperQuery 'input'.

*/ void /*

setRelNameOnAlias(Relation& relation);

Function: This function parses the 'line' and read in the first word as the key value into 'keyv'. Input: It takes in 'keyv' and 'line'. OutPut: Returns nothing, but updates 'keyv' with the key value.

*/ void /*

It makes sure the relation name and the relation alias match. Takes in the relation. outputs nothing but set m_relName based on m_alias.

parseIf(SuperQuery& input, string& line);

Function: If keyv's value is WHERE this function is called to parse the WHERE clause. Input: It takes in 'line' as a string and 'input', keyv and the input file stream and the output file stream.. OutPut: Returns nothing but updates the SuperQuery 'input'.

*/ void parseWhere(SuperQuery& input, string& keyv, string& line, ifstream& in, ofstream& outFile); /*

Function: A subfunction of parseWhere parsing job. Input: It takes in the position of dot (posD) and the equal sign posEq been parsed in ParseWhere. OutPut: Returns nothing but updates accordingly.

which actually does most of the AND and the next AND, and the positio in the WHERE clause which all have the values of the 'input' variables

*/ void parseWhere1(SuperQuery& input,string& line,size_t posAnd,size_t posAnd2, size_t posD,size_t posEq ); // *********************** /*

Generate Tree headers ****************

Function: This function generates nodes based on the 'input' and its SELECT, FROM and WHERE. Page 5 of 8


Header.h

1/15/15, 3:30 AM

Input: It basically reads in the 'input' SuperQuery and 'graph' GraphViz file. Output: Returns nothing, but updates the 'graph' file.*/ void generateNode(SuperQuery const input, GraphViz& graph, ofstream& algebraicRelation); /*

Function: This fuction creates a node based on the inputs. Most commonly used function in the code. Input: It takes in all the parameters that are needed to generate a node. It needs a string for the operation 'operation', a string for the middle section 'middlePart, the node number for the left child 'left' and the node number for the right child, 'right', and the node number for the node being generated 'nodeSeq'. A 'relation', a boolean which is used to determine whether or not there is a second part to the node. and an 'attribute' which is the attribute name of eahc middle part. Output: It returns nothing, but updates 'graph' with the node number specified. */ void nodify (GraphViz& graph, string operation, string middlePart, int left, int right, int nodeSeq, Relation const relation, int const boolean, string const attribute); /*

Function: To create a there is neither an the main query. Input: Take in the Output: Updates the void nodifyCase1(SuperQuery algebraicRelation);

GraphViz file according the the Query input file when intermediate operation nor a nested query within input and the graph. graph and returns none.*/ const input, GraphViz& graph, ofstream&

/*

Function: To create a GraphViz file according the the Query input file when there is not a nested query within the main query but there is an intermediate operation. Input: Take in the input and the graph. Output: Updates the graph and returns none.*/ void nodifyCase2(SuperQuery const input, GraphViz& graph, ofstream& algebraicRelation); /*

Fuction: It is the process through which a SuperQuery 'input' file generates a GraphViz 'graph' file to be create a Query tree when the input query has a nested query but not intermediate operation. Input: It takes in the input, graph, and output file stream. Output: It reuturns none but updates the graph file and accordingly. */ void nodifyCase3 (SuperQuery const input, GraphViz& graph, ofstream& outFile, ofstream& algebraicRelation); /*

Function: To create a GraphViz file according the the Query input file when there is both an intermediate operation and a nested query within the main query. Input: Take in the input and the graph. Output: Updates the graph and returns none.*/ void nodifyCase4(SuperQuery const input,GraphViz& graph, ofstream& algebraicRelation); /*

Function: After the graphViz is created, this function actually creates a query tree based on that. Input: It takes in the graph and output fiel stream. Page 6 of 8


Header.h

1/15/15, 3:30 AM

output: It generates the output file, which is already initiated as .dot file.*/ void generateTree(GraphViz& graph,ofstream& outFile); /*

Function: This function finds the expression with a constant value on the right side, and the relation corresponding to that, and creates a node right above that relation which is being joined, with the expression. Input: Input the Query 'input' file and the 'graph' file. output: Returns none, and updates the 'graph' according the optimization process.*/ void expediteSelect(SuperQuery const input, GraphViz& graph); /*

Function: When a node has two parts, mostly in the case of WHERE where an expression has two sides, this function is used to compelete the second half. Input: Takes in the 'graph', a relation corresponding to the right hand side, a boolean to indicate whether it is constant or an attribute, and the node number, and the attribute name. Output: Returns none, and update the graph.*/ void nodify2(GraphViz& graph, Relation const relation, bool const boolean, int const nodeSeq, string const attribute); /* Function: After a 'graph' file is update, each time this function needs to be called to careate one string for the middle Part. Input: Takes in the 'graph'. Output: Returns none and updates the graph. */ void createMiddlePart(GraphViz& graph);//Creates a midddle section that goes along with a node a graph Viz file. /*

Function: This function creates a integer array inside the down, where the first integere indicates the number of, and the rest of the array contain the node number to those nodes that are in the nodes branches below it. Input: Input the 'graph'. Output: Returns none, and updates the 'graph' file.*/ void createDownSet (GraphViz& graph); /*

Function: Just like the previous function, it creates an integer array where each integer is the node number of those nodes above this node. The first integer indicates the number of nodes. Input: Takes in the 'graph' file. Output: Returns none and updates the 'graph' file with the integer array.*/ void createUpSet (GraphViz& graph); /*

Function: As an optimization process, for every relation that is being joined with other relations, this function search for every attribute from this relation which is participating in the query and performs the PROJECT operation right above the relation as early as possible. Input: Takes in the 'graph'. Output: Returns none, and updates the graph, with the optimization process */ void expediteProject(GraphViz& graph); /*

Function: This function creates a node between two other nodes that are parent and child. Input: It takes in the 'graph', the node number to the node which will be below 'bot, and the node number which will be above, 'top'. Add is the random number which will be added to the 'bot' to create a node number Page 7 of 8


Header.h

1/15/15, 3:30 AM

for the node being created. A string for 'operation' of the node and the string for the 'middle'part' of the node. Output: Returns nothing, but creates in node inside the 'graph.*/ void createNodeBetweeen(GraphViz& graph, int const top, int const bot, int const add, string const operation, string const midPart); /*

Function: If a node has a bowTie operation, this function looks at both sides of each expression and the relation corresponding to that, and if those relations are both in either left or right of the node, that expression will be move down one node in that direction. Input: Takes in the 'graph'. Output: updates the 'graph' with the optimization process and returns none.*/ void expediteBowTie(GraphViz& graph); #endif

Page 8 of 8


Header.cpp

// // // // // // // //

1/15/15, 3:30 AM

DataBase Systems Project: CS 5300 Missouri University of Science and Technology Professor: Dr. Ali Hurson Created by Hadi on 12/21/14. Copyright (c) 2014 Hadi. All rights reserved.

This file includes all the function definitions and operator overloading definitions. #include <algorithm> #include "Header.h" #include<string> #include<fstream>//include #include<iostream> #include <ctime> #include<vector> #include <cstdlib> using namespace std; Relation Relation::operator = (const Relation& source) { m_name = source.m_name; m_alias = source.m_alias; return (*this); }; bool Relation::operator == (const Relation& source) { if ((m_alias == source.m_alias)) return true; else if (m_name == source.m_name) return true; else return false; }; Node Node::operator=(const Node& source) { m_operation = source.m_operation; for(int i=0;i<100;++i) { m_midPart[i].m_relation[0] = source.m_midPart[i].m_relation[0]; m_midPart[i].m_relation[1] = source.m_midPart[i].m_relation[1]; m_midPart[i].m_wholeThing = source.m_midPart[i].m_wholeThing; } m_middlePart = source.m_middlePart; m_midSeq = source.m_midSeq; m_left = source.m_left; m_right = source.m_right; m_upLine = source.m_upLine; m_useNode = source.m_useNode; m_nodeSet = source.m_nodeSet; return (*this); }; Page 1 of 26


Header.cpp

1/15/15, 3:30 AM

GraphViz GraphViz::operator=(const GraphViz &source) { for(int i = 0; i<100;++i) { m_nodes[i] = source.m_nodes[i]; } m_noOfNodes = source.m_noOfNodes; return (*this); }; int count (string line, string find) { int number = 0; size_t pos=0; pos = line.find(find,pos); while(pos!=line.npos)//If the text inside find exists in line then add one to number. { number ++; pos = line.find(find,pos+1); } return number; }; int count (string line, char find) { int number = 0; size_t pos=0; pos = line.find(find,pos); while(pos!=line.npos)//If the text inside find exists in line then add one to number. { number ++; pos = line.find(find,pos+1); } return number; }; // ***************************************************************************** ***** //********************** Initiate ************************************************* // ***************************************************************************** ***** void initiate(string& keyv, string& line, ifstream& in, ofstream& outFile, ofstream& optFile, ofstream& algebraicRelation) { char fileName[50];// Definition of variables. char outName[50], optName[50];// Page 2 of 26


Header.cpp

1/15/15, 3:30 AM

char relAlg[50]; in.clear(); cout<< "Please enter the filename:"<<endl; cin.getline(fileName, 50); for(int i = 0; i<40;i++) cout<<fileName[i]; in.open(fileName); for(int i = 0;i<7;++i) { relAlg[i] = fileName[i]; outName[i] = fileName[i]; optName[i] = fileName[i]; } strcat(outName, ".dot"); strcat(optName, " optimized.dot"); outFile.open(outName); optFile.open(optName); strcat(relAlg, " relAlgeb.dot"); algebraicRelation.open(relAlg); outFile<<"digraph G {\nnode [ color=\"transparent\" ]\nedge [ dir=none ]\n"; optFile<<"digraph G {\nnode [ color=\"transparent\" ]\nedge [ dir=none ]\n"; algebraicRelation<<"digraph G {\nnode [ color=\"transparent\" ]\nedge [ dir=none ]\n"; }; // ***************************************************************************** ***** //********************** Read Keyv ********************************************** // ***************************************************************************** ***** void readKeyv(string& keyv, string& line) { size_t posTab = line.find('\t',0);// Find the position of tab in line. if (posTab==line.npos)//)If tab's pos is npos then there is a two part query. Set the boolean value for the intermediate value as true. { posTab = line.npos +1; } keyv = line.substr (0,posTab); }; void setRelNameOnAlias(Relation& relation) { if ((relation.m_alias == "R") || (relation.m_alias == "R2")) relation.m_name = "Reserves"; if (relation.m_alias == "S" || relation.m_alias == "S2") relation.m_name = "Sailors"; if (relation.m_alias == "B" || relation.m_alias == "B2") relation.m_name = "Boats"; }; // Page 3 of 26


Header.cpp

1/15/15, 3:30 AM

***************************************************************************** ***** //********************** SELECT ************************************************* // ***************************************************************************** ***** void parseSelect(SuperQuery& input, string& line) { //int cc = count(line, ','); //for(int j = 0;j<cc;++j) //{ int i = input.m_seq; size_t posD = line.find('.'); size_t posTab = line.find('\t'); if (posD != line.npos)//if '.' exists in line. it means alias is used. { input.m_inQuery[i].m_slct.m_attName = line.substr (posD+1);// input.m_inQuery[i].m_slct.m_relation.m_alias = line.substr(posTab+1, posD-(posTab+1));//Set the alias as whatever is between AS+3 and next comma-1. input.m_inQuery[i].m_slct.m_useAlias = true; } else if (posD == line.npos)//if '.' does not exist in line. No alias is used. { input.m_inQuery[i].m_slct.m_attName = line.substr(posTab+1); input.m_inQuery[i].m_slct.m_useAlias = false; if(input.m_inQuery[i].m_slct.m_attName=="sname") input.m_inQuery[i].m_slct.m_relation.m_alias = "S"; } input.m_inQuery[i].m_slct.m_allPhrase = line.substr(posTab + 1); setRelNameOnAlias(input.m_inQuery[i].m_slct.m_relation); }; // ***************************************************************************** ***** //********************** FROM ************************************************** // ***************************************************************************** ***** void parseIf(SuperQuery& input, string& line, string& keyv) { int i = input.m_seq; size_t posTab = line.find('\t'); size_t posCom = posTab -1; size_t posCom2 = 0; size_t posAs = line.find("AS"); //look for 'AS' as posAs

Page 4 of 26


Header.cpp

1/15/15, 3:30 AM

if (posAs !=line.npos)// If "AS" exists in line input.m_inQuery[i].m_frm.m_useAlias = true;//then there will be aliases used. else input.m_inQuery[i].m_frm.m_useAlias = false; //otherwise no aliases used. input.m_inQuery[i].m_frm.m_relCount = count(line.begin(),line.end(),',') + 1;//count the number of ',' which determines the number of relations used in From. place the count+1 and save it in an member variable in FROM. for (int j = 0; j < input.m_inQuery[i].m_frm.m_relCount; ++j)//Do the following iteration the same as the number of relations in From. { if (j ==input.m_inQuery[i].m_frm.m_relCount -1 )// When we are parsing the last relation for the From Clause: posCom2 = line.length();// Then make the position of comma2 as the last position on the string. else { posCom2 = line.find(',', posCom + 1);// Find the position of the comma after the previous comma. } if (input.m_inQuery[i].m_frm.m_useAlias == true)// If aliases are used in From. { input.m_inQuery[i].m_frm.m_relation[j].m_name = line.substr(posCom+2, posAs-1-(posCom+2)); //Relation name is the whatever is between comma and AS. input.m_inQuery[i].m_frm.m_relation[j].m_alias = line.substr(posAs+3, posCom2-(posAs+3));// Relation Alias is between AS and the comma after that. posAs = line.find("AS",posAs+1);//Find the position of AS and put it in posAS. } else if (input.m_inQuery[i].m_frm.m_useAlias == false)//otherwise if there is no alias used: { input.m_inQuery[i].m_frm.m_relation[j].m_name = line.substr(posCom+2, posCom2 - (posCom +2));//relation's name in index "i" is whatever is between first comma and second comma input.m_inQuery[i].m_frm.m_relation[j].m_alias = ""; } input.m_inQuery[i].m_frm.m_allPhrase[j] = line.substr(posCom+2, posCom2 (posCom +2));//Regardless there is a variable to store the entire phrase of relation. posCom = line.find(',', posCom +1);// Find the position of the comma after the previous comma. setRelNameOnAlias(input.m_inQuery[i].m_frm.m_relation[j]); } }; Page 5 of 26


Header.cpp

1/15/15, 3:30 AM

// ***************************************************************************** ***** //********************** WHERE ************************************************** // ***************************************************************************** ***** //********* ParseWhere 1 ************** void parseWhere1(SuperQuery& input,string& line,size_t posAnd,size_t posAnd2, size_t posD,size_t posEq ) { int i = input.m_seq; size_t posC=0; size_t posT = line.find("\t"); string word; string alias; input.m_inQuery[i].m_whr.m_allWhere = line.substr(posT+1); if(input.m_inQuery[i].m_whr.m_allWhere.find(">") != input.m_inQuery[i].m_whr. m_allWhere.npos)// If there is an ">" inside there condition: { posC = input.m_inQuery[i].m_whr.m_allWhere.find(">"); if(posC != input.m_inQuery[i].m_whr.m_allWhere.npos) { input.m_inQuery[i].m_whr.m_allWhere.replace(posC, 1 , ">");// replace it with the unicode corresponding to it. } } if(input.m_inQuery[i].m_whr.m_allWhere.find("\324") != input.m_inQuery[i]. m_whr.m_allWhere.npos) { posC = input.m_inQuery[i].m_whr.m_allWhere.find("\324"); if(posC != input.m_inQuery[i].m_whr.m_allWhere.npos) { input.m_inQuery[i].m_whr.m_allWhere.replace(posC, 1 , "'"); } posC = input.m_inQuery[i].m_whr.m_allWhere.find("\325"); if(posC != input.m_inQuery[i].m_whr.m_allWhere.npos) { input.m_inQuery[i].m_whr.m_allWhere.replace(posC, 1, "'"); } } input.m_inQuery[i].m_whr.m_nested = false;//there is no nest. input.m_inQuery[i].m_whr.m_noCond = count(line,"AND")+1;//count the number of occurences of AND in a Where clause: that would be then number of conditions in Where. for(int j = 0; j < input.m_inQuery[i].m_whr.m_noCond; j++)//Do the iterations for the number of conditions. Page 6 of 26


Header.cpp

1/15/15, 3:30 AM

{ posAnd2 = line.find("AND", posAnd +1);//And2 is the position of the next AND. input.m_inQuery[i].m_whr.m_condition[j].m_left.m_relation.m_name= line. substr(posAnd + 4, posD- (posAnd + 4));// The name of the left side relation is between AND and the next dot. if (input.m_inQuery[i].m_whr.m_condition[j].m_left.m_relation.m_name. length()<3)//Then it is an ALIAS { input.m_inQuery[i].m_whr.m_condition[j].m_left.m_relation.m_alias = input.m_inQuery[i].m_whr.m_condition[j].m_left.m_relation.m_name; setRelNameOnAlias(input.m_inQuery[i].m_whr.m_condition[j].m_left. m_relation); } input.m_inQuery[i].m_whr.m_condition[j].m_left.m_attribute = line.substr (posD + 1, posEq- (posD + 1));// The left hand side attribute is between the dot and the second AND input.m_inQuery[i].m_whr.m_condition[j].m_string = line.substr(posAnd + 4 , posAnd2 - (posAnd+4)); if(input.m_inQuery[i].m_whr.m_condition[j].m_string.find(">") != input. m_inQuery[i].m_whr.m_condition[j].m_string.npos)// If there is an ">" inside there condition: { posC = input.m_inQuery[i].m_whr.m_condition[j].m_string.find(">"); if(posC != input.m_inQuery[i].m_whr.m_condition[j].m_string.npos) { input.m_inQuery[i].m_whr.m_condition[j].m_string.replace(posC, 1 , ">");//replace it with the unicode corresponding to it. } } if(input.m_inQuery[i].m_whr.m_condition[j].m_string.find("\324") != input .m_inQuery[i].m_whr.m_condition[j].m_string.npos) { posC = input.m_inQuery[i].m_whr.m_condition[j].m_string.find("\324"); if(posC != input.m_inQuery[i].m_whr.m_condition[j].m_string.npos) { input.m_inQuery[i].m_whr.m_condition[j].m_string.replace(posC, 1 , "'"); } posC = input.m_inQuery[i].m_whr.m_condition[j].m_string.find("\325"); if(posC != input.m_inQuery[i].m_whr.m_condition[j].m_string.npos) { input.m_inQuery[i].m_whr.m_condition[j].m_string.replace(posC, 1, "'"); } } word = line.substr(posEq + 1, posAnd2 - (posEq + 1)); if(word.find('.')!= word.npos)//If there is a dot it means there is no constant value on right side: Page 7 of 26


Header.cpp

1/15/15, 3:30 AM

{ posD = line.find('.', posD + 1); input.m_inQuery[i].m_whr.m_condition[j].m_right.m_useConst = false;// So set use of Const to false. input.m_inQuery[i].m_whr.m_condition[j].m_right.m_string = "";//empty out the constant var. input.m_inQuery[i].m_whr.m_condition[j].m_right.m_attribute = line. substr(posD +1, posAnd2-(posD +1));//set the attribute name to whatever is between second AND and the DOT. input.m_inQuery[i].m_whr.m_condition[j].m_right.m_relation.m_name = line.substr(posEq + 1, posD-(posEq + 1));//right hand side's relation is between the Eq. sign and the dot. if (input.m_inQuery[i].m_whr.m_condition[j].m_right.m_relation.m_name .length()<3)//Then it is an ALIAS { input.m_inQuery[i].m_whr.m_condition[j].m_right.m_relation. m_alias = input.m_inQuery[i].m_whr.m_condition[j].m_right. m_relation.m_name; } alias = input.m_inQuery[i].m_whr.m_condition[j].m_right.m_relation. m_alias; setRelNameOnAlias(input.m_inQuery[i].m_whr.m_condition[j].m_right. m_relation); } else//Otherwise there is a constant value on right side. { input.m_inQuery[i].m_whr.m_condition[j].m_right.m_useConst = true; input.m_inQuery[i].m_whr.m_condition[j].m_right.m_string = word; // Place the substring into the appropriate variable which is m_string. input.m_inQuery[i].m_whr.m_condition[j].m_right.m_relation.m_name=""; input.m_inQuery[i].m_whr.m_condition[j].m_right.m_relation.m_alias = ""; input.m_inQuery[i].m_whr.m_condition[j].m_right.m_attribute=""; } posEq = line.find_first_of("=><", posEq +1);//Find the position of the next character that matches any of them. posAnd = posAnd2; //posAnd = line.find("AND", posAnd + 1);//Find hte position of the next AND. posD = line.find('.',posD+1); } }; //******************

ParseWhere Main

*********************************

void parseWhere(SuperQuery& input, string& keyv, string& line, ifstream& in, ofstream& outFile) { Page 8 of 26


Header.cpp

1/15/15, 3:30 AM

//****** Declare Variables ************************************************** size_t posIn = line.find("IN");// Located the position first 'IN" and place it in posIn. size_t posTab = line.find("\t"); size_t posAnd = line.find('\t')-3;//Since there is no AND before the first relation we use AND. size_t posD = line.find('.');// size_t posEq = line.find_first_of("=><"); size_t posAnd2 = 0; string word; // ********************* Parsing ***************************************** if (posIn!= line.npos)//If there is an "IN" then: { input.m_seq = 2; input.m_inQuery[0].m_whr.m_condition[0].m_left.m_string = line.substr (posTab+1, posIn-1 -(posTab + 1)); input.m_inQuery[0].m_whr.m_condition[0].m_left.m_relation.m_alias =line. substr(posTab+1,posD-(posTab+1)); input.m_inQuery[0].m_whr.m_condition[0].m_left.m_attribute = line.substr (posD+1, posIn-1-(posD+1)); input.m_nested = true;// Also make sure the query know that is has a nested query. input.m_inQuery[0].m_whr.m_condition[0].m_left.m_relation.m_alias = line. substr(posTab+1, posD-(posTab+1)); setRelNameOnAlias(input.m_inQuery[0].m_whr.m_condition[0].m_left. m_relation); ScanNQuery(input, in, keyv, line); } else if (posAnd!= line.npos)// If there is AND inside WHERE clause then { parseWhere1(input, line, posAnd, posAnd2, posD, posEq ); } }; // ***************************************************************************** ***** //********************** ScanQuery ********************************************** // ***************************************************************************** ***** // *********************** Nested Query ***************************************** void ScanNQuery(SuperQuery& input, ifstream& in, string& keyv, string& line) { input.m_seq = 2; ofstream outFile; Page 9 of 26


Header.cpp

1/15/15, 3:30 AM

while(getline(in,line)) { readKeyv(keyv, line);

// While the ifstream in is not finished:

if (keyv.compare("SELECT") == 0) { parseSelect(input, line); } if (keyv.compare("FROM") == 0) { parseIf(input, line, keyv); } if (keyv.compare("WHERE")==0) { parseWhere(input, keyv, line, in, outFile); } if ((keyv.compare("EXCEPT")==0) || (keyv.compare("UNION")==0) || (keyv. compare("INTERSECT")==0)) { input.m_twoPartInOP = keyv; input.m_twoPart = true; Scan2Query(input, in, keyv, line); } }; }; // *********************** Two part Query ***************************************** void Scan2Query(SuperQuery& input, ifstream& in, string& keyv, string& line) { input.m_seq = 1; ofstream outFile; while(getline(in,line)) { outFile<<line; outFile<<'\n'; readKeyv( keyv, line);

// While the ifstream in is not finished:

if (keyv.compare("SELECT") == 0) { parseSelect(input, line); } if (keyv.compare("FROM") == 0) { parseIf(input,line, keyv); }

Page 10 of 26


Header.cpp

1/15/15, 3:30 AM

if (keyv.compare("WHERE")==0) { parseWhere(input, keyv, line, in, outFile); } }; }; //************************** Original ******************************************************** void ScanQuery(SuperQuery& input, ifstream& in, string& keyv, string& line) { ofstream outFile; while(getline(in,line)) // While the ifstream in is not finished: { outFile<<line; outFile<<'\n'; readKeyv(keyv, line); if (keyv.compare("SELECT") == 0) { parseSelect(input, line); } if (keyv.compare("FROM") == 0) { parseIf(input,line, keyv); } if (keyv.compare("WHERE")==0) { parseWhere(input, keyv, line, in, outFile); } if ((keyv.compare("EXCEPT")==0) || (keyv.compare("UNION")==0) || (keyv. compare("INTERSECT")==0)) { input.m_seq = 1; input.m_twoPart = true; input.m_twoPartOp = keyv; Scan2Query(input, in, keyv, line); } } }; // ***************************************************************************** ***** //********************** Generate nodes ***************************************** // ***************************************************************************** Page 11 of 26


Header.cpp

1/15/15, 3:30 AM

***** //**************************** generate NODES ************************************* void nodify (GraphViz& graph, string operation, string middlePart, int left, int right, int nodeSeq, Relation const relation, bool const boolean, string const attribute)// Creates a node based on the input parameters. { string project = "Π"; string bowTie = "⨝"; string select = "σ"; string empty = ""; graph.m_nodes[nodeSeq].m_operation = operation;//Set the operation var. in the node to the input. if(middlePart!=empty)//If there is an actual input for the middle section: { graph.m_nodes[nodeSeq].m_midPart[graph.m_nodes[nodeSeq].m_midSeq]. m_wholeThing = middlePart;//Creates the middle section the consitutes the main part. graph.m_nodes[nodeSeq].m_midPart[graph.m_nodes[nodeSeq].m_midSeq]. m_relation[0]= relation; graph.m_nodes[nodeSeq].m_midPart[graph.m_nodes[nodeSeq].m_midSeq]. m_attribute[0] = attribute; } graph.m_nodes[nodeSeq].m_useNode = true; graph.m_nodes[nodeSeq].m_left = left; graph.m_nodes[nodeSeq].m_right = right; if (left != 0) { graph.m_nodes[left].m_upLine = nodeSeq; } if (right != 0) { graph.m_nodes[right].m_upLine = nodeSeq; } graph.m_nodes[nodeSeq].m_nodeSet = true; if(boolean) ++graph.m_nodes[nodeSeq].m_midSeq; }; void nodify2(GraphViz& graph, Relation const relation, bool const boolean, int const nodeSeq, string const attribute) { if(!boolean)//If there is not constant in the right hand side of an expression: { graph.m_nodes[nodeSeq].m_midPart[graph.m_nodes[nodeSeq].m_midSeq]. m_relation[1] = relation; graph.m_nodes[nodeSeq].m_midPart[graph.m_nodes[nodeSeq].m_midSeq]. m_relation[1].m_constant = boolean; graph.m_nodes[nodeSeq].m_midPart[graph.m_nodes[nodeSeq].m_midSeq]. m_attribute[1] = attribute; Page 12 of 26


Header.cpp

1/15/15, 3:30 AM

} else { graph.m_nodes[nodeSeq].m_midPart[graph.m_nodes[nodeSeq].m_midSeq]. m_relation[1].m_constant = boolean; } ++graph.m_nodes[nodeSeq].m_midSeq; }; void nodifyCase1(SuperQuery const input, GraphViz& graph, ofstream& algebraicRelation) { string project = "Π"; string bowTie = "⨝"; string select = "σ"; string empty = ""; string temp = ""; int j = 0; nodify( graph, project, input.m_inQuery[0].m_slct.m_allPhrase, 1, 0, 0, input.m_inQuery[0].m_slct.m_relation, true, input.m_inQuery[0].m_slct. m_attName); for (int i = 0; i<input.m_inQuery[0].m_whr.m_noCond; ++i)//Nodify the WHERE Clause. { nodify( graph, bowTie, input.m_inQuery[0].m_whr.m_condition[i].m_string, 2, 3, 1, input.m_inQuery[0].m_whr.m_condition[i].m_left.m_relation, false, input.m_inQuery[0].m_whr.m_condition[i].m_left.m_attribute ); nodify2(graph,input.m_inQuery[0].m_whr.m_condition[i].m_right.m_relation , input.m_inQuery[0].m_whr.m_condition[i].m_right.m_useConst, 1, input.m_inQuery[0].m_whr.m_condition[i].m_right.m_attribute); ++j; if (j==4) break; }; for (int i = 0; i<input.m_inQuery[0].m_frm.m_relCount; ++i)// Nodify FROM { if(input.m_inQuery[0].m_frm.m_relCount < 3)// If number of from Relations are less than three { nodify( graph, empty, input.m_inQuery[0].m_frm.m_allPhrase[i], 0, 0, i+2, input.m_inQuery[0].m_frm.m_relation[i], true, empty); graph.m_nodes[1].m_left = 2; graph.m_nodes[1].m_right = 3; } else if(input.m_inQuery[0].m_frm.m_relCount ==3) { nodify( graph, empty, input.m_inQuery[0].m_frm.m_allPhrase[i], 0, 0, i+3, input.m_inQuery[0].m_frm.m_relation[i], true, empty); graph.m_nodes[2].m_operation =bowTie; Page 13 of 26


Header.cpp

1/15/15, 3:30 AM

graph.m_nodes[2].m_useNode = true; graph.m_nodes[1].m_left = 2; graph.m_nodes[1].m_right = 3; graph.m_nodes[2].m_left = 4; graph.m_nodes[2].m_right = 5; graph.m_nodes[2].m_upLine = 1; graph.m_nodes[1].m_upLine = 0; graph.m_nodes[3].m_upLine = 1; graph.m_nodes[4].m_upLine = 2; graph.m_nodes[5].m_upLine = 2; } } algebraicRelation<<"node0 [ label = <<SUB> "; temp = project + "(" + input.m_inQuery[0].m_slct.m_allPhrase+") "+ "(" + input.m_inQuery[0].m_frm.m_allPhrase[0] + " " + bowTie + "("+ input. m_inQuery[0].m_whr.m_allWhere + ") " + "(" + input.m_inQuery[0].m_frm. m_allPhrase[1]; algebraicRelation<<temp; if(input.m_inQuery[0].m_frm.m_relCount ==3) { temp = bowTie + "(" + input.m_inQuery[0].m_frm.m_allPhrase[2] + ")"; algebraicRelation <<temp; } algebraicRelation<<")"; algebraicRelation<<"</SUB>>]\n}"; }; void nodifyCase2(SuperQuery const input, GraphViz& graph, ofstream& algebraicRelation) { string project = "Π"; string bowTie = "⨝"; string select = "σ"; string empty = ""; string twoPartCode = ""; string temp = ""; Relation dummy; dummy.m_name = ""; dummy.m_alias = ""; if(input.m_twoPartOp == "UNION") { twoPartCode = "∪"; } if(input.m_twoPartOp == "INTERSECT") { twoPartCode = "⋂"; } if(input.m_twoPartOp == "EXCEPT") { twoPartCode = "-"; } nodify( graph, twoPartCode, empty, 1, 2, 0, dummy, true, empty); Page 14 of 26


Header.cpp

1/15/15, 3:30 AM

nodify( graph,project, input.m_inQuery[0].m_slct.m_allPhrase, 3, 0, 1, input. m_inQuery[0].m_slct.m_relation, true, input.m_inQuery[0].m_slct.m_attName ); nodify( graph, project, input.m_inQuery[1].m_slct.m_allPhrase, 4, 0, 2, input .m_inQuery[1].m_slct.m_relation, true, input.m_inQuery[1].m_slct. m_attName); for (int i = 0; i<input.m_inQuery[0].m_whr.m_noCond; ++i)//Nodify the WHERE Clause. { nodify( graph,bowTie, input.m_inQuery[0].m_whr.m_condition[i].m_string, 5 , 6, 3, input.m_inQuery[0].m_whr.m_condition[i].m_left.m_relation, false, input.m_inQuery[0].m_whr.m_condition[i].m_left.m_attribute); nodify2(graph, input.m_inQuery[0].m_whr.m_condition[i].m_right.m_relation , input.m_inQuery[0].m_whr.m_condition[i].m_right.m_useConst, 3, input.m_inQuery[0].m_whr.m_condition[i].m_right.m_attribute); nodify( graph, bowTie, input.m_inQuery[1].m_whr.m_condition[i].m_string, 8, 9, 4, input.m_inQuery[1].m_whr.m_condition[i].m_left.m_relation, false, input.m_inQuery[1].m_whr.m_condition[i].m_left.m_attribute); nodify2(graph, input.m_inQuery[1].m_whr.m_condition[i].m_right.m_relation , input.m_inQuery[1].m_whr.m_condition[i].m_right.m_useConst, 4, input.m_inQuery[1].m_whr.m_condition[i].m_right.m_attribute); }; for(int l=0;l<2;++l) { for (int i = 0; i<input.m_inQuery[l].m_frm.m_relCount; ++i)// Nodify FROM { if(input.m_inQuery[l].m_frm.m_relCount < 3) { nodify( graph, empty, input.m_inQuery[l].m_frm.m_allPhrase[i], 0, 0, 2*l + 5 + i, input.m_inQuery[l].m_frm.m_relation[i], true, empty); } else if(input.m_inQuery[l].m_frm.m_relCount ==3) { nodify( graph, empty, input.m_inQuery[l].m_frm.m_allPhrase[i], 0, 0, 3*l + 5 + i, input.m_inQuery[l].m_frm.m_relation[i], true, empty); nodify( graph, bowTie, empty, 3*l +6, 3*l+7, l+11, dummy, true, empty); graph.m_nodes[l+3].m_right = l+11; graph.m_nodes[l+11].m_upLine = l + 3; } } } //**************************************************** algebraicRelation<<"node0 [ label = <<SUB> "; temp = " (" + project + "(" + input.m_inQuery[0].m_slct.m_allPhrase+") "+ "(" + input.m_inQuery[0].m_frm.m_allPhrase[0] + " " + bowTie + "("+ input .m_inQuery[0].m_whr.m_allWhere + ") " + "(" + input.m_inQuery[0].m_frm. Page 15 of 26


Header.cpp

1/15/15, 3:30 AM

m_allPhrase[1]; algebraicRelation<<temp; if(input.m_inQuery[0].m_frm.m_relCount ==3) { temp = bowTie + "(" + input.m_inQuery[0].m_frm.m_allPhrase[2] + ")"; algebraicRelation <<temp; } algebraicRelation<<")))"; algebraicRelation<<twoPartCode; temp = " (" + project + "(" + input.m_inQuery[1].m_slct.m_allPhrase+") "+ "(" + input.m_inQuery[1].m_frm.m_allPhrase[0] + " " + bowTie + "("+ input .m_inQuery[1].m_whr.m_allWhere + ") " + "(" + input.m_inQuery[1].m_frm. m_allPhrase[1]; algebraicRelation<<temp; if(input.m_inQuery[1].m_frm.m_relCount ==3) { temp = bowTie + "(" + input.m_inQuery[1].m_frm.m_allPhrase[2] + ")"; algebraicRelation <<temp; } algebraicRelation<<")"; algebraicRelation<<") "; algebraicRelation<<"</SUB>>]\n}"; }; void nodifyCase3 (SuperQuery const input, GraphViz& graph, ofstream& algebraicRelation) { string project = "Π"; string bowTie = "⨝"; string select = "σ"; string empty = ""; string twoPartCode = ""; string middlePart = input.m_inQuery[0].m_whr.m_condition[0].m_left.m_string + "=" + input.m_inQuery[2].m_slct.m_allPhrase; string temp = ""; nodify( graph, project, input.m_inQuery[0].m_slct.m_allPhrase, 1, 0, 0, input.m_inQuery[0].m_slct.m_relation, true, input.m_inQuery[0].m_slct. m_attName); nodify( graph, bowTie, middlePart, 2, 3, 1, input.m_inQuery[0].m_whr. m_condition[0].m_left.m_relation, false, input.m_inQuery[0].m_whr. m_condition[0].m_left.m_attribute); nodify2(graph, input.m_inQuery[2].m_slct.m_relation, false, 1, input. m_inQuery[2].m_slct.m_attName); nodify( graph, empty, input.m_inQuery[0].m_frm.m_allPhrase[0], 0, 0, 2,input .m_inQuery[0].m_frm.m_relation[0], true, empty); nodify(graph, project, input.m_inQuery[2].m_slct.m_allPhrase, 4, 0, 3, input. m_inQuery[2].m_slct.m_relation, true, input.m_inQuery[2].m_slct.m_attName ); nodify( graph, select, input.m_inQuery[2].m_whr.m_condition[0].m_string, 5, 0, 4, input.m_inQuery[2].m_whr.m_condition[0].m_left.m_relation, false, input.m_inQuery[2].m_whr.m_condition[0].m_left.m_attribute); nodify2(graph, input.m_inQuery[2].m_whr.m_condition[0].m_right.m_relation, Page 16 of 26


Header.cpp

1/15/15, 3:30 AM

input.m_inQuery[2].m_whr.m_condition[0].m_right.m_useConst, 4, input. m_inQuery[2].m_whr.m_condition[0].m_right.m_attribute); nodify( graph, empty, input.m_inQuery[2].m_frm.m_allPhrase[0], 0, 0, 5, input.m_inQuery[2].m_frm.m_relation[0], true, empty); //****************** algebraicRelation<<"node0 [ label = <<SUB> "; temp = " (" + project + "(" + input.m_inQuery[0].m_slct.m_allPhrase+") "+ "(" + input.m_inQuery[0].m_frm.m_allPhrase[0] + " " + bowTie + "("+ middlePart + ") " + "( " + project + "( " + input.m_inQuery[2].m_slct. m_allPhrase + "( "+input.m_inQuery[2].m_frm.m_allPhrase[0] + "( "+ select +"( "+input.m_inQuery[2].m_whr.m_allWhere + ")))))))"; algebraicRelation<<temp; algebraicRelation<<"</SUB>>]\n}"; }; void nodifyCase4(SuperQuery const input,GraphViz& graph, ofstream& algebraicRelation) { string project = "Π"; string bowTie = "⨝"; string select = "σ"; string empty = ""; string twoPartCode = empty; string middlePart = input.m_inQuery[0].m_whr.m_condition[0].m_left.m_string + "=" + input.m_inQuery[2].m_slct.m_allPhrase; string temp = ""; Relation dummy; if(input.m_twoPartInOP == "UNION") { twoPartCode = "∪"; } if(input.m_twoPartInOP == "INTERSECT") { twoPartCode = "⋂"; } if(input.m_twoPartInOP == "EXCEPT") { twoPartCode = "-"; } nodify( graph, project, input.m_inQuery[0].m_slct.m_allPhrase, 1, 0, 0, input.m_inQuery[0].m_slct.m_relation, true, input.m_inQuery[0].m_slct. m_attName); nodify( graph, bowTie, middlePart, 2, 3, 1, input.m_inQuery[0].m_whr. m_condition[0].m_left.m_relation, false, input.m_inQuery[0].m_whr. m_condition[0].m_left.m_attribute); nodify2(graph, input.m_inQuery[2].m_slct.m_relation, false, 1, input. m_inQuery[2].m_slct.m_attName); nodify( graph, empty, input.m_inQuery[0].m_frm.m_allPhrase[0], 0, 0, 2, input.m_inQuery[0].m_frm.m_relation[0], true, empty); Page 17 of 26


Header.cpp

1/15/15, 3:30 AM

nodify( graph, twoPartCode, empty,4,5,3, dummy, true, empty); nodify( graph, project, input.m_inQuery[2].m_slct.m_allPhrase, 6, 0, 4, input.m_inQuery[2].m_slct.m_relation, true, input.m_inQuery[2].m_slct. m_attName); nodify( graph, project, input.m_inQuery[1].m_slct.m_allPhrase, 7, 0, 5, input.m_inQuery[1].m_slct.m_relation, true, input.m_inQuery[1].m_slct. m_attName); for (int l=2;l>0;--l) { for (int i = 0; i<input.m_inQuery[l].m_whr.m_noCond; ++i)//Nodify the WHERE Clause. { nodify( graph, bowTie, input.m_inQuery[l].m_whr.m_condition[i]. m_string,12 - 2*l, 13- 2*l, 8-l, input.m_inQuery[l].m_whr. m_condition[i].m_left.m_relation, false, input.m_inQuery[l].m_whr .m_condition[i].m_left.m_attribute); nodify2(graph, input.m_inQuery[l].m_whr.m_condition[i].m_right. m_relation, input.m_inQuery[l].m_whr.m_condition[i].m_right. m_useConst, 8-l, input.m_inQuery[l].m_whr.m_condition[i].m_right. m_attribute); } } for(int l = 2;l>0;--l) { for (int i = 0;i<2;++i) { nodify( graph, empty, input.m_inQuery[l].m_frm.m_allPhrase[i], 0, 0 , 4/l +6 + i, input.m_inQuery[l].m_frm.m_relation[i], true, empty ); } } //********************************************************************* algebraicRelation<<"node0 [ label = <<SUB> "; temp = project + "(" + input.m_inQuery[0].m_slct.m_allPhrase+") "+ "(" + input.m_inQuery[0].m_frm.m_allPhrase[0] + " " + bowTie + "("+ middlePart + ") ( "; algebraicRelation<<temp; temp = " (" + project + "(" + input.m_inQuery[2].m_slct.m_allPhrase+") "+ "(" + input.m_inQuery[2].m_frm.m_allPhrase[0] + " " + bowTie + "("+ input .m_inQuery[2].m_whr.m_allWhere + ") " + "(" + input.m_inQuery[2].m_frm. m_allPhrase[1]; algebraicRelation<<temp; if(input.m_inQuery[2].m_frm.m_relCount ==3) { temp = bowTie + "(" + input.m_inQuery[2].m_frm.m_allPhrase[2] + ")"; algebraicRelation <<temp; } algebraicRelation<<")))"; algebraicRelation<<twoPartCode; temp =

" (" + project + "(" + input.m_inQuery[1].m_slct.m_allPhrase+") "+ Page 18 of 26


Header.cpp

1/15/15, 3:30 AM

"(" + input.m_inQuery[1].m_frm.m_allPhrase[0] + " " + bowTie + "("+ input .m_inQuery[1].m_whr.m_allWhere + ") " + "(" + input.m_inQuery[1].m_frm. m_allPhrase[1]; algebraicRelation<<temp; if(input.m_inQuery[1].m_frm.m_relCount ==3) { temp = bowTie + "(" + input.m_inQuery[1].m_frm.m_allPhrase[2] + ")"; algebraicRelation <<temp; } algebraicRelation<<")"; algebraicRelation<<") "; algebraicRelation<<"</SUB>>]\n}"; }; void generateTree(GraphViz& graph,ofstream& outFile) { for(int k =0;k<40;++k) { if(graph.m_nodes[k].m_useNode == true) { outFile<<"node"<< k <<" [ label = <"<<graph.m_nodes[k].m_operation<<"<SUB> "<<graph.m_nodes[k]. m_middlePart<<" </SUB>>] \n"; if(graph.m_nodes[k].m_left != 0) { outFile<<"node"<< k <<" -> "<< "node"<<graph.m_nodes[k].m_left<<"\n"; } if(graph.m_nodes[k].m_right != 0) { outFile<<"node"<< k <<" -> "<< "node"<<graph.m_nodes[k].m_right<<"\n"; } } } outFile<<"} \n"; }; void createMiddlePart(GraphViz& graph) { for(int k =0;k<40;++k) { graph.m_nodes[k].m_middlePart = ""; if(graph.m_nodes[k].m_useNode == true) { for (int m = 0; m<graph.m_nodes[k].m_midSeq;++m) { if(graph.m_nodes[k].m_midPart[m].m_wholeThing!="" & graph.m_nodes [k].m_midPart[m].m_wholeThing!=" ") graph.m_nodes[k].m_middlePart = graph.m_nodes[k].m_middlePart + "(" + graph.m_nodes[k].m_midPart[m].m_wholeThing + ")"; } } Page 19 of 26


Header.cpp

1/15/15, 3:30 AM

} }; void generateNode(SuperQuery const input, GraphViz& graph, ofstream& algebraicRelation ) { string project = "Π"; string bowTie = "⨝"; string select = "σ"; string empty = ""; if(input.m_nested == false) { if(input.m_twoPart ==false) { nodifyCase1(input, graph, algebraicRelation); } else if (input.m_twoPart == true) { nodifyCase2(input, graph, algebraicRelation); } } else if (input.m_nested == true) { if(input.m_twoPart == false) { nodifyCase3(input, graph, algebraicRelation); } else if (input.m_twoPart == true) { nodifyCase4(input,graph, algebraicRelation); } } }; // ***************************************************************************** ***** //********************** Optimization ***************************************** // ***************************************************************************** ***** void expediteSelect(SuperQuery const input, GraphViz& graph)// scan nodes for uprelation { string project = "Π"; string bowTie = "⨝"; string select = "σ"; string empty = ""; int add = 10; Page 20 of 26


Header.cpp

1/15/15, 3:30 AM

Relation dummy; Node node; for(int i = 20; i>0; --i)//counting the nodes from 0 to 40 which is the last node. { bool one = graph.m_nodes[i].m_useNode; bool two = graph.m_nodes[i].m_operation == ""; if(one & two) { for(int j = 1;j < graph.m_nodes[i].m_upSet[0] + 4; ++j) { int k = graph.m_nodes[i].m_upSet[j]; for (int l = 0;l< graph.m_nodes[i].m_midSeq+4; ++l) { string string1 = graph.m_nodes[i].m_midPart[0].m_relation[0]. m_name; string string2 = graph.m_nodes[k].m_midPart[l].m_relation[0]. m_name; string word =graph.m_nodes[k].m_midPart[l].m_wholeThing; bool result1 = graph.m_nodes[k].m_midPart[l].m_relation[1]. m_name == "" ; bool result2 = string2 == string1; bool result3 = word.find("'") != word.npos; bool result5 = graph.m_nodes[k].m_operation == bowTie; if (((result1 || result3 ) & result5 & result2 )) { createNodeBetweeen(graph, graph.m_nodes[i].m_upLine, i, add, select, graph.m_nodes[k].m_midPart[l]. m_wholeThing); add = add +2; graph.m_nodes[k].m_midPart[l].m_wholeThing = ""; } } } } } }; void createDownSet(GraphViz& graph) { for (int m = 25; m > 0-1; --m) { bool boolean = true; int k = 3; if (graph.m_nodes[m].m_left != 0) { graph.m_nodes[m].m_downSet[1] = graph.m_nodes[m].m_left; for(int n = 1; n < graph.m_nodes[graph.m_nodes[m].m_left].m_downSet[0 ]+2; ++n) { if (graph.m_nodes[graph.m_nodes[m].m_left].m_downSet[n]!=0) { graph.m_nodes[m].m_downSet[k] = graph.m_nodes[graph.m_nodes[m ].m_left].m_downSet[n]; Page 21 of 26


Header.cpp

1/15/15, 3:30 AM

++k; } } } else if (graph.m_nodes[m].m_right == 0) { graph.m_nodes[graph.m_nodes[m].m_left].m_downSet[0] = 0; boolean = false; } if (graph.m_nodes[m].m_right != 0) { graph.m_nodes[m].m_downSet[2] = graph.m_nodes[m].m_right; for(int n = 1; n<graph.m_nodes[graph.m_nodes[m].m_right].m_downSet[0] +2; ++n) { if(graph.m_nodes[graph.m_nodes[m].m_right].m_downSet[n]!=0) { graph.m_nodes[m].m_downSet[k] = graph.m_nodes[graph.m_nodes[m ].m_right].m_downSet[n]; ++k; } } } else if (graph.m_nodes[m].m_left == 0) { graph.m_nodes[graph.m_nodes[m].m_right].m_downSet[0] = 0; boolean = false; } if (boolean) graph.m_nodes[m].m_downSet[0] = k-1; for(int l = 1 ; l<25; ++l) { if(graph.m_nodes[m].m_downSet[l] == 0) { for (int p = l+1; p<graph.m_nodes[m].m_downSet[0]+2;++p) { if ((graph.m_nodes[m].m_downSet[p] != 0)&(graph.m_nodes[m]. m_downSet[p] < 25)) { graph.m_nodes[m].m_downSet[l] = graph.m_nodes[m]. m_downSet[p]; graph.m_nodes[m].m_downSet[p] = 0; ++l; } } } } } }; void createUpSet (GraphViz& graph) { for (int m = 25; m >0; --m) { Page 22 of 26


Header.cpp

1/15/15, 3:30 AM

int k = 1; int j = graph.m_nodes[m].m_upLine; while(j!=0) { graph.m_nodes[m].m_upSet[k] = j; ++k; j = graph.m_nodes[j].m_upLine; } graph.m_nodes[m].m_upSet[0] = k; for(int l = 1 ; l<25; ++l)//skipping zero and putting the numbers next to one another in the array. { if(graph.m_nodes[m].m_upSet[l] == 0) { for (int p = l+1; p<graph.m_nodes[m].m_upSet[0]+2;++p) { if ((graph.m_nodes[m].m_upSet[p] != 0)&(graph.m_nodes[m]. m_upSet[p] < 25)) { graph.m_nodes[m].m_upSet[l] = graph.m_nodes[m].m_upSet[p] ; graph.m_nodes[m].m_upSet[p] = 0; ++l; } } } } } }; void expediteProject(GraphViz& graph) { string project = "Π"; string bowTie = "⨝"; string select = "σ"; string empty = ""; string midPart = ""; int const add = 21; Relation dummy; for(int i=25;i>0-1;--i) { cout<<endl<<"this is I: "<<i<<endl; string midPart = ""; string middlePart[10]={""}; int partNum=0; bool one = graph.m_nodes[i].m_useNode; bool two = graph.m_nodes[i].m_operation == ""; if(one & two) { string string1 = graph.m_nodes[i].m_midPart[0].m_relation[0].m_name; string string2 = graph.m_nodes[0].m_midPart[0].m_relation[0].m_name; if(string1==string2) { middlePart[partNum] = graph.m_nodes[0].m_midPart[0].m_attribute Page 23 of 26


Header.cpp

1/15/15, 3:30 AM

[0]; if(middlePart[partNum]!= middlePart[partNum -1]) { if(midPart != "") { midPart = midPart + ","; midPart = midPart + " " + middlePart[partNum]; } else midPart = midPart + middlePart[partNum]; } ++partNum; } int j = graph.m_nodes[i].m_upLine; while(j!=0) { for (int l = 0; l<graph.m_nodes[j].m_midSeq + 2; ++l) { string1 = graph.m_nodes[i].m_midPart[0].m_relation[0].m_name; string2 = graph.m_nodes[j].m_midPart[l].m_relation[0].m_name; if (string1 == string2) { middlePart[partNum] = graph.m_nodes[j].m_midPart[l]. m_attribute[0]; if(middlePart[partNum]!= middlePart[partNum -1]) { if(midPart != "") { midPart = midPart + ","; midPart = midPart + " " + middlePart[partNum]; } else midPart = midPart + middlePart[partNum]; } ++partNum; } string2 = graph.m_nodes[j].m_midPart[l].m_relation[1].m_name; if( string1 == string2) { middlePart[partNum] = graph.m_nodes[j].m_midPart[l]. m_attribute[1]; if(middlePart[partNum]!= middlePart[partNum -1]) { if(midPart != "") { midPart = midPart + ","; midPart = midPart + " " + middlePart[partNum]; } else midPart = midPart + middlePart[partNum]; } ++partNum; } } Page 24 of 26


Header.cpp

1/15/15, 3:30 AM

cout<<endl<<"What is j? "<<j<<endl; j = graph.m_nodes[j].m_upLine; cout<<endl<<"What is j2? "<<j<<endl; } createNodeBetweeen(graph, graph.m_nodes[i].m_upLine, i, add, project, midPart); } } }; void createNodeBetweeen(GraphViz& graph, int const top, int const bot, int const add, string const operation, string const midPart) { string project = "Π"; string bowTie = "⨝"; string select = "σ"; string empty = ""; Relation dummy; if(graph.m_nodes[graph.m_nodes[bot].m_upLine].m_right == bot) { cout<<endl<<"1111Top is: "<<top<<endl<<"Bottom is: "<<bot<< endl<<"Add is: "<<add<<endl; graph.m_nodes[top].m_right = add + bot;// Change the upline's left downline relation to the new node. graph.m_nodes[bot].m_upLine = add+ bot; nodify(graph, operation, midPart, 0, bot, add + bot, dummy, true, empty);// move that condition above the ith node. graph.m_nodes[add + bot].m_upLine = top; } else if(graph.m_nodes[graph.m_nodes[bot].m_upLine].m_left == bot) { cout<<endl<<"2222Top is: "<<top<<endl<<"Bottom is: "<<bot<< endl<<"Add is: "<<add<<endl; graph.m_nodes[top].m_left = add + bot;// Change the upline's left downline relation to the new node. graph.m_nodes[bot].m_upLine = add + bot; nodify( graph, operation, midPart, bot, 0, add + bot, dummy, true, empty) ;// move that condition above the ith node. graph.m_nodes[add + bot].m_upLine = top; } }; void {

expediteBowTie(GraphViz& graph)

string project = "Π"; string bowTie = "⨝"; string select = "σ"; string empty = ""; Relation dummy; for (int i = 0; i<25; ++i) { int target = 0; Page 25 of 26


Header.cpp

1/15/15, 3:30 AM

if((graph.m_nodes[i].m_operation == bowTie) & graph.m_nodes[i]. m_middlePart != empty) { for(int j = 1; j<graph.m_nodes[i].m_downSet[0]+4; ++j) { int k = graph.m_nodes[i].m_downSet[j]; if((k != 0)&(graph.m_nodes[k].m_operation == bowTie)&(graph. m_nodes[k].m_middlePart ==empty)) { target = k; cout<<endl<<"What is the target???? "<<target<<endl; for(int m = 0; m < graph.m_nodes[i].m_midSeq + 3; ++m) { int left = graph.m_nodes[target].m_left; int right = graph.m_nodes[target].m_right; cout<<"What is left: "<<left<<endl; cout<<"What is right: "<<right<<endl; string string1 = graph.m_nodes[i].m_midPart[m].m_relation [0].m_name; string string2 = graph.m_nodes[i].m_midPart[m].m_relation [1].m_name; string string3 = graph.m_nodes[left].m_midPart[0]. m_relation[0].m_name; string string4 = graph.m_nodes[right].m_midPart[0]. m_relation[0].m_name; bool res1 = string1 == string3 & string2 == string4; bool res2 = string2 == string3 & string1 == string4; bool res3 = string1!= empty; bool res4 = string2!= empty; if((res1 || res2) & res3 & res4) { cout<<endl<<"string1 is: "<<string1<<endl; cout<<endl<<"string2 is: "<<string2<<endl; cout<<endl<<"string3 is: "<<string3<<endl; cout<<endl<<"string4 is: "<<string4<<endl; graph.m_nodes[target].m_midPart[0].m_wholeThing = graph.m_nodes[i].m_midPart[m].m_wholeThing; cout<<endl<<"What is this wholethign youre talking about?"<<graph.m_nodes[i].m_midPart[m]. m_wholeThing<<endl; graph.m_nodes[i].m_midPart[m].m_wholeThing = ""; } } } } } } };

Page 26 of 26


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.