Ejemplo n.º 1
0
/////////BDB//////Check for matching number of columns/////////////////////
void Table::addRow(vector<string> columnNames, vector<string> rowData) {
	for(int i = 0; i < columnNames.size(); i++) {
		Column *thisCol = findColumn(columnNames[i]);
		if(thisCol == NULL) {
			throw DatabaseException(20, "Column " + columnNames[i] + " does not exist.");
		}
		if(thisCol->isPrimaryKey() && thisCol->valExists(rowData[i])) {
			throw DatabaseException(21, rowData[i] + " already exists in column" + columnNames[i] + ".");
		}
		thisCol->addRow(rowData[i]);
	}
}
Ejemplo n.º 2
0
/**
 * This will evalute the tree
 * It uses type safety returns a string of the result
 */
string ExpressionTree::evaluate() {
	string num;

	if (!replaceable) {
		if (left == NULL || right == NULL) {
			throw DatabaseException(18,
					"Must have both left and right side to evaluate.");
		}
		string left_side = left->evaluate();
		string right_side = right->evaluate();

		string result;
		int type1 = valType(left_side); //0 is string
		//1 is float
		//2 is int
		//3 is date
		//4 is time
		int type2 = valType(right_side);
//		cout << "LEFT TYPE IS " << type1;
//		cout << " LEFT IS " << left_side << endl;
//		cout << "RIGHT TYPE IS " << type2;
//		cout << " RIGHT IS " << right_side << endl;
//		cout << "OPERATION IS" << value << endl;
		int intLeft;
		int intRight;
		float floatLeft;
		float floatRight;
		string stringLeft = left_side;
		string stringRight = right_side;
		Date dateLeft;
		Date dateRight;
		Time timeLeft;
		Time timeRight;
		stringstream leftStream(left_side);
		stringstream rightStream(right_side);
		switch (type1) {
		case 2:
			leftStream >> intLeft;
			break;
		case 1:
			leftStream >> floatLeft;
			break;
		case 3:
			leftStream >> dateLeft;
			break;
		case 4:
			leftStream >> timeLeft;
			break;
		}
		switch (type2) {
		case 2:
			rightStream >> intRight;
			break;
		case 1:
			rightStream >> floatRight;
			break;
		case 3:
			rightStream >> dateRight;
			break;
		case 4:
			rightStream >> timeRight;
			break;
		}
		//FIXX: Make sure type1 == type2, except for int and float
		Operations SWITCH = operation_map[value];
		switch (SWITCH) {
		//what she is doing
		case EQUAL: {
			bool tempResult;
			if (type1 == 0 && type2 == 0) {
				tempResult = (stringLeft == stringRight);
			} else if (type1 == 1 && type2 == 1) {
				tempResult = (floatLeft == floatRight);
			} else if (type1 == 1 && type2 == 2) {
				tempResult = (floatLeft == (float) intRight);
			} else if (type1 == 2 && type2 == 1) {
				tempResult = ((float) intLeft == floatRight);
			} else if (type1 == 2 && type2 == 2) {
				tempResult = (intLeft == intRight);
			} else if (type1 == 3 && type2 == 3) {
				tempResult = (dateLeft == dateRight);
			} else if (type1 == 4 && type2 == 4) {
				tempResult = (timeLeft == timeRight);
			} else {
				throw DatabaseException(
						18,
						intTypeToString(type1) + " and "
								+ intTypeToString(type2)
								+ " can not be compared using the == operator");
			}
			result = tempResult ? "1" : "0";
		}
			break;
		case NOT_EQUAL: {
			bool tempResult;
			if (type1 == 0 && type2 == 0) {
				tempResult = (stringLeft != stringRight);
			} else if (type1 == 1 && type2 == 1) {
				tempResult = (floatLeft != floatRight);
			} else if (type1 == 1 && type2 == 2) {
				tempResult = (floatLeft != (float) intRight);
			} else if (type1 == 2 && type2 == 1) {
				tempResult = ((float) intLeft != floatRight);
			} else if (type1 == 2 && type2 == 2) {
				tempResult = (intLeft != intRight);
			} else if (type1 == 3 && type2 == 3) {
				tempResult = (dateLeft != dateRight);
			} else if (type1 == 4 && type2 == 4) {
				tempResult = (timeLeft != timeRight);
			} else {
				throw DatabaseException(
						18,
						intTypeToString(type1) + " and "
								+ intTypeToString(type2)
								+ " can not be compared using the != operator");
			}
			result = tempResult ? "1" : "0";
		}
			break;
		case LTE: {
			bool tempResult;
			if (type1 == 0 && type2 == 0) {
				tempResult = (stringLeft <= stringRight);
			} else if (type1 == 1 && type2 == 1) {
				tempResult = (floatLeft <= floatRight);
			} else if (type1 == 1 && type2 == 2) {
				tempResult = (floatLeft <= (float) intRight);
			} else if (type1 == 2 && type2 == 1) {
				tempResult = ((float) intLeft <= floatRight);
			} else if (type1 == 2 && type2 == 2) {
				tempResult = (intLeft <= intRight);
			} else if (type1 == 3 && type2 == 3) {
				tempResult = (dateLeft <= dateRight);
			} else if (type1 == 4 && type2 == 4) {
				tempResult = (timeLeft <= timeRight);
			} else {
				throw DatabaseException(
						18,
						intTypeToString(type1) + " and "
								+ intTypeToString(type2)
								+ " can not be compared using the <= operator");
			}
			result = tempResult ? "1" : "0";
		}
			break;
		case GTE: {
			bool tempResult;
			if (type1 == 0 && type2 == 0) {
				tempResult = (stringLeft >= stringRight);
			} else if (type1 == 1 && type2 == 1) {
				tempResult = (floatLeft >= floatRight);
			} else if (type1 == 1 && type2 == 2) {
				tempResult = (floatLeft >= (float) intRight);
			} else if (type1 == 2 && type2 == 1) {
				tempResult = ((float) intLeft >= floatRight);
			} else if (type1 == 2 && type2 == 2) {
				tempResult = (intLeft >= intRight);
			} else if (type1 == 3 && type2 == 3) {
				tempResult = (dateLeft >= dateRight);
			} else if (type1 == 4 && type2 == 4) {
				tempResult = (timeLeft >= timeRight);
			} else {
				throw DatabaseException(
						18,
						intTypeToString(type1) + " and "
								+ intTypeToString(type2)
								+ " can not be compared using the >= operator");
			}
			result = tempResult ? "1" : "0";
		}
			break;
		case LT: {
			bool tempResult;
			if (type1 == 0 && type2 == 0) {
				tempResult = (stringLeft < stringRight);
			} else if (type1 == 1 && type2 == 1) {
				tempResult = (floatLeft < floatRight);
			} else if (type1 == 1 && type2 == 2) {
				tempResult = (floatLeft < (float) intRight);
			} else if (type1 == 2 && type2 == 1) {
				tempResult = ((float) intLeft < floatRight);
			} else if (type1 == 2 && type2 == 2) {
				tempResult = (intLeft < intRight);
			} else if (type1 == 3 && type2 == 3) {
				tempResult = (dateLeft < dateRight);
			} else if (type1 == 4 && type2 == 4) {
				tempResult = (timeLeft < timeRight);
			} else {
				throw DatabaseException(
						18,
						intTypeToString(type1) + " and "
								+ intTypeToString(type2)
								+ " can not be compared using the < operator");
			}
			result = tempResult ? "1" : "0";
		}
			break;
		case GT: {
			bool tempResult;
			if (type1 == 0 && type2 == 0) {
				tempResult = (stringLeft > stringRight);
			} else if (type1 == 1 && type2 == 1) {
				tempResult = (floatLeft > floatRight);
			} else if (type1 == 1 && type2 == 2) {
				tempResult = (floatLeft > (float) intRight);
			} else if (type1 == 2 && type2 == 1) {
				tempResult = ((float) intLeft > floatRight);
			} else if (type1 == 2 && type2 == 2) {
				tempResult = (intLeft > intRight);
			} else if (type1 == 3 && type2 == 3) {
				tempResult = (dateLeft > dateRight);
			} else if (type1 == 4 && type2 == 4) {
				tempResult = (timeLeft > timeRight);
			} else {
				throw DatabaseException(
						18,
						intTypeToString(type1) + " and "
								+ intTypeToString(type2)
								+ " can not be compared using the > operator");
			}
			result = tempResult ? "1" : "0";
		}
			break;

			//parse it into a 1 or 0 do operation store in result
		case AND: {
			if ((type1 == 2 && type2 == 2) && intLeft < 2 && intRight < 2
					&& intLeft >= 0 && intRight >= 0) {
				//the bitwise and operation will the same as the normal && operation on a bool
				result = ((intLeft & intRight) == 1) ? "1" : "0";
			} else {
				throw DatabaseException(
						18,
						intTypeToString(type1) + " and "
								+ intTypeToString(type2)
								+ " can not be compared using the && operator");
			}
		}
			break;

		case OR: {
			if ((type1 == 2 && type2 == 2) && intLeft < 2 && intRight < 2
					&& intLeft >= 0 && intRight >= 0) {
				//the bitwise or operation will the same as the normal || operation on a bool
				result = ((intLeft | intRight) == 1) ? "1" : "0";
			} else {
				throw DatabaseException(
						18,
						intTypeToString(type1) + " and "
								+ intTypeToString(type2)
								+ " can not be compared using the && operator");
			}
		}
			break;

			//parse it into a number do operation, store into result
		case EXP:
			if (type1 != 1 && type1 != 2) {
				throw DatabaseException(18,
						stringLeft + " must be a float or int type.");
			} else if (type2 != 1 && type2 != 2) {
				throw DatabaseException(18,
						stringRight + " must be a float or int type.");
			}

			float val;

			//Convert the first value to a float
			if (type2 == 1) {
				val = (float) intRight;
			} else {
				val = floatRight;
			}

			//Get the result depending on the left value
			if (type1 == 1) {
				result = (int) pow(intLeft, val);
			} else {
				result = pow(floatLeft, val);
			}
			break;
		case MULT:
			if (type1 != 1 && type1 != 2) {
				throw DatabaseException(18,
						stringLeft + " must be a float or int type.");
			} else if (type2 != 1 && type2 != 2) {
				throw DatabaseException(18,
						stringRight + " must be a float or int type.");
			}

			if (type1 == 1) {
				if (type2 == 1) {
					result = intLeft * intRight;
				} else {
					result = intLeft * floatRight;
				}
			} else {
				if (type2 == 1) {
					result = floatLeft * intRight;
				} else {
					result = floatLeft * floatRight;
				}
			}

			break;
		case DIVIDE:
			if (type1 != 1 && type1 != 2) {
				throw DatabaseException(18,
						stringLeft + " must be a float or int type.");
			} else if (type2 != 1 && type2 != 2) {
				throw DatabaseException(18,
						stringRight + " must be a float or int type.");
			}
			if (type1 == 1) {
				if (type2 == 1) {
					result = intLeft / intRight;
				} else {
					result = intLeft / floatRight;
				}
			} else {
				if (type2 == 1) {
					result = floatLeft / intRight;
				} else {
					result = floatLeft / floatRight;
				}
			}

			break;
		case PLUS:
			if (type1 != 1 && type1 != 2) {
				throw DatabaseException(18,
						stringLeft + " must be a float or int type.");
			} else if (type2 != 1 && type2 != 2) {
				throw DatabaseException(18,
						stringRight + " must be a float or int type.");
			}
			if (type1 == 1) {
				if (type2 == 1) {
					result = intLeft + intRight;
				} else {
					result = intLeft + floatRight;
				}
			} else {
				if (type2 == 1) {
					result = floatLeft + intRight;
				} else {
					result = floatLeft + floatRight;
				}
			}

			break;
		case MINUS:
			if (type1 != 1 && type1 != 2) {
				throw DatabaseException(18,
						stringLeft + " must be a float or int type.");
			} else if (type2 != 1 && type2 != 2) {
				throw DatabaseException(18,
						stringRight + " must be a float or int type.");
			}
			if (type1 == 1) {
				if (type2 == 1) {
					result = intLeft - intRight;
				} else {
					result = intLeft - floatRight;
				}
			} else {
				if (type2 == 1) {
					result = floatLeft - intRight;
				} else {
					result = floatLeft - floatRight;
				}
			}

			break;
		case ALL:
		case ANY: {
//			cout<<"ANY OR ALL"<<endl;
//			cout<<stringLeft<<endl;
//			cout<<stringRight<<endl;
			//stringLeft = table.col
			//stringRight = table_one_col
			Column * leftCol = NULL;
			try {
				leftCol = db->findColumn(stringLeft);
			} catch (DatabaseException e) {
//				cout<<"ignore exception"<<endl;
			}
			if (leftCol == NULL) {
				leftCol = new Column(valueType(stringLeft));
				leftCol->addRow(stringLeft);
			}
			string leftColType = leftCol->getColumnType();

			Table * rightTable = db->findTable(stringRight);
			if (rightTable == NULL) {
				throw DatabaseException(10, stringRight + " does not exist.");
			}
			Column * rightTableColumn = rightTable->findColumn(
					rightTable->columnNames()[0]);
			string rightTableColType = rightTableColumn->getColumnType();

			if (rightTable->columnCount() != 1) {
				throw DatabaseException(18,
						stringRight + " must have 1 column for ANY/ALL.");
			} else if (leftColType.compare(rightTableColType) != 0
					&& !((leftColType == "int" && rightTableColType == "float")
							|| (leftColType == "float"
									&& rightTableColType == "int"))) {
				throw DatabaseException(
						13,
						leftColType + " is not the same as "
								+ rightTableColType);
			}

			int funcType = -1;
			string op = "";
			switch (SWITCH) {
			case ANY:
				funcType = 1;
				op = value.substr(0, value.find("ANY"));
				break;
			case ALL:
				funcType = 2;
				op = value.substr(0, value.find("ALL"));
				break;
			}
			LogicHandler * temp = new LogicHandler("LEFT" + op + "RIGHT");
			temp->parse();
			vector<string> inserts;
			inserts.push_back("LEFT");
			inserts.push_back("RIGHT");
			ExpressionTree * tree = temp->getTree();

			for (int i = 0; i < leftCol->rowCount(); i++) {

				string leftInput = leftCol->getValueAtRowIndex(i);

//				cout<<"\n\nLEFT INPUT IS "<<leftInput<<endl;
//				cout<<"\n\nfollows "<<leftCol->printDataList()<<"index is "<<i<<endl;

				for (int j = 0; j < rightTableColumn->rowCount(); j++) {
					string rightInput = rightTableColumn->getValueAtRowIndex(j);
					vector<string> throwaway;
					throwaway.push_back(leftInput);
					throwaway.push_back(rightInput);
					bool eval = tree->isTrue(inserts, throwaway);

					if (funcType == 1 && eval) {
						return "1";
					} else if (funcType == 2 && !eval) {
						return "0";
					}
				}
			}

			result = (funcType == 1) ? "0" : "1";

		}
			break;
		case IN: //FIXX: Does not catch if the column types differ. Convert types
		{
			result = "0";

			if (db->countColumnsByTable(stringRight) != 1) {
				throw DatabaseException(18,
						stringRight + " does not have only 1 column.");
			}

			Table *theTable = db->findTable(stringRight);

			vector<string> column = theTable->columnNames();

			Column *theColumn = theTable->findColumn(column[0]);

			for (int i = 0; i < theColumn->rowCount(); i++) {
				if (stringLeft == theColumn->getValueAtRowIndex(i)) {
					result = "1";
					break;
				}
			}

		}
			break;
		case EXIST: {
			Table * table = db->findTable(stringRight);
			if (table == NULL) {
				result = "0";
			} else if (table->columnCount() >= 1) {
				result = "1";
			} else {
				result = "0";
			}
		}
			break;
		}
		num = result;
		//this is an operation
	} else {