diff --git a/.gitignore b/.gitignore
index a11aeca..4af70df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,5 @@ target/
.idea/
run-designite.bat
output-designite/
+usr/
+src/main/java/com/dal/distributed/constant/VMConstants.java
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..c5f3f6b
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "java.configuration.updateBuildConfiguration": "interactive"
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 0ca4215..d99c94f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,6 +15,11 @@
commons-codec
1.15
+
+ com.jcraft
+ jsch
+ 0.1.55
+
diff --git a/src/main/java/com/dal/distributed/analytics/Analytics.java b/src/main/java/com/dal/distributed/analytics/Analytics.java
new file mode 100644
index 0000000..e9e2bc6
--- /dev/null
+++ b/src/main/java/com/dal/distributed/analytics/Analytics.java
@@ -0,0 +1,205 @@
+package com.dal.distributed.analytics;
+
+import com.dal.distributed.constant.DataConstants;
+import com.dal.distributed.constant.QueryRegex;
+import com.dal.distributed.constant.VMConstants;
+import com.dal.distributed.logger.Logger;
+import com.dal.distributed.queryImpl.model.QueryLog;
+import com.dal.distributed.utils.FileOperations;
+import com.dal.distributed.utils.RemoteVmUtils;
+
+import java.io.File;
+import java.util.*;
+import java.util.regex.Matcher;
+
+public class Analytics {
+ Logger logger = Logger.instance();
+
+ public void analyze(Scanner scanner) throws Exception {
+ while (true) {
+ logger.info("\nPlease choose any one of the following options:");
+ logger.info("1. Analytics");
+ logger.info("2. Exit");
+ String input = scanner.nextLine();
+
+ switch (input) {
+ case "1":
+ logger.info("Please input a query for the selected option: ");
+ String query = scanner.nextLine();
+ analyzeQueries(query);
+ break;
+ case "2":
+ break;
+ default:
+ logger.error("Please choose a valid input!");
+ }
+ if ("2".equals(input))
+ break;
+ }
+ }
+
+ private void analyzeQueries(String queryString) throws Exception {
+ String[] query = queryString.split(" ");
+ if (query[1].contains("queries")) {
+ countQueries(queryString);
+ } else if (query[1].contains("update")) {
+ countOperationType("UPDATE");
+ } else if (query[1].contains("insert")) {
+ countOperationType("INSERT");
+ } else if (query[1].contains("delete")) {
+ countOperationType("DELETE");
+ } else if (query[1].contains("select")) {
+ countOperationType("SELECT");
+ } else if (query[1].contains("create")) {
+ countOperationType("CREATE TABLE");
+ }
+ }
+
+ private void countOperationType(String operation) throws Exception {
+ List queryLogs = getQueryLogFileInformation();
+ HashMap tableMap = new HashMap<>();
+ for (QueryLog queryLog : queryLogs) {
+ if (queryLog.getOperation().equalsIgnoreCase(operation)) {
+ if (null != tableMap.get(queryLog.getTableName())) {
+ tableMap.put(queryLog.getTableName(), tableMap.get(queryLog.getTableName()) + 1);
+ } else {
+ tableMap.put(queryLog.getTableName(), 1);
+ }
+ }
+ }
+
+ Boolean flag = Boolean.FALSE;
+ for (Map.Entry user : tableMap.entrySet()) {
+ logger.info("Total " + user.getValue() + " " + operation + " operation(s) are performed on " + user.getKey());
+ flag = Boolean.TRUE;
+ }
+
+ if (!flag) {
+ logger.info("No " + operation + " queries found.");
+ }
+ }
+
+ private void countQueries(String queryString) throws Exception {
+ String [] query = queryString.split(" ");
+ Matcher matcher = QueryRegex.countQueriesAnalytics.matcher(queryString);
+ if (matcher.find()) {
+ String userName = matcher.group(1).trim();
+ String databaseName = matcher.group(2).replace(";","");
+ countQueriesForUser(userName, databaseName);
+ } else if (query.length == 2) {
+ countTotalQueries();
+ }
+ }
+
+ private void countTotalQueries() throws Exception {
+ List queryLogs = getQueryLogFileInformation();
+ HashMap userMap = new HashMap<>();
+ for (QueryLog queryLog : queryLogs) {
+ String key = queryLog.getSubmittedBy() + "|" + queryLog.getDatabaseName();
+ if (null != userMap.get(key)) {
+ userMap.put(key, userMap.get(key) + 1);
+ } else {
+ userMap.put(key, 1);
+ }
+ }
+
+ Boolean flag = Boolean.FALSE;
+ for (Map.Entry user : userMap.entrySet()) {
+ String[] details = user.getKey().split("\\|");
+ if (null != details[1] && !details[1].equalsIgnoreCase("null")) {
+ logger.info("User " + details[0] + " submitted " + user.getValue() + " query(s) for " + details[1]);
+ }
+ flag = Boolean.TRUE;
+ }
+
+ if (!flag) {
+ logger.info("No queries found");
+ }
+ }
+
+ private void countQueriesForUser(String userName, String databaseName) throws Exception {
+ List queryLogs = getQueryLogFileInformation();
+ HashMap userMap = new HashMap<>();
+ for (QueryLog queryLog : queryLogs) {
+ if (queryLog.getDatabaseName().equalsIgnoreCase(databaseName) &&
+ queryLog.getSubmittedBy().equalsIgnoreCase(userName)) {
+ if (null != userMap.get(queryLog.getSubmittedBy())) {
+ userMap.put(queryLog.getSubmittedBy(), userMap.get(queryLog.getSubmittedBy()) + 1);
+ } else {
+ userMap.put(queryLog.getSubmittedBy(), 1);
+ }
+ }
+ }
+
+ Boolean flag = Boolean.FALSE;
+ for (Map.Entry user : userMap.entrySet()) {
+ logger.info("User " + user.getKey() + " submitted " + user.getValue() + " query(s) for " + databaseName);
+ flag = Boolean.TRUE;
+ }
+
+ if (!flag) {
+ logger.info("No queries found");
+ }
+ }
+
+ private List getQueryLogFileInformation() throws Exception {
+ String queryLogFile = FileOperations.readFileContent(
+ new File(DataConstants.LOGS_FILE_LOCATION + DataConstants.QUERY_LOG_FILE_NAME));
+
+ String remoteQueryLogFile = RemoteVmUtils.readFileContent(VMConstants.projectPath + DataConstants.LOGS_FILE_LOCATION + DataConstants.QUERY_LOG_FILE_NAME);
+ StringBuilder sb = new StringBuilder()
+ .append(queryLogFile)
+ .append(remoteQueryLogFile);
+
+ Matcher matcher = QueryRegex.valueBetweenQuotes.matcher(sb.toString());
+ List queryLogList = new ArrayList<>();
+
+ //JSON to Java Object List
+ while (matcher.find()) {
+ if (matcher.group().equalsIgnoreCase("QueryLog")) {
+ QueryLog queryLog = new QueryLog();
+ while (matcher.find()) {
+ if (matcher.group().equalsIgnoreCase("flag")) {
+ matcher.find();
+ if (matcher.find()) {
+ queryLog.setFlag(matcher.group());
+ }
+ } else if (matcher.group().equalsIgnoreCase("query")) {
+ matcher.find();
+ if (matcher.find()) {
+ queryLog.setQuery(matcher.group());
+ }
+ } else if (matcher.group().equalsIgnoreCase("operation")) {
+ matcher.find();
+ if (matcher.find()) {
+ queryLog.setOperation(matcher.group());
+ }
+ } else if (matcher.group().equalsIgnoreCase("submissionTimestamp")) {
+ matcher.find();
+ if (matcher.find()) {
+ queryLog.setSubmissionTimestamp(matcher.group());
+ }
+ } else if (matcher.group().equalsIgnoreCase("submittedBy")) {
+ matcher.find();
+ if (matcher.find()) {
+ queryLog.setSubmittedBy(matcher.group());
+ }
+ } else if (matcher.group().equalsIgnoreCase("tableName")) {
+ matcher.find();
+ if (matcher.find()) {
+ queryLog.setTableName(matcher.group());
+ }
+ } else if (matcher.group().equalsIgnoreCase("databaseName")) {
+ matcher.find();
+ if (matcher.find()) {
+ queryLog.setDatabaseName(matcher.group());
+ }
+ break;
+ }
+ }
+ queryLogList.add(queryLog);
+ }
+ }
+ return queryLogList;
+ }
+}
diff --git a/src/main/java/com/dal/distributed/authentication/Login.java b/src/main/java/com/dal/distributed/authentication/Login.java
index e654a8d..eeff554 100644
--- a/src/main/java/com/dal/distributed/authentication/Login.java
+++ b/src/main/java/com/dal/distributed/authentication/Login.java
@@ -1,5 +1,6 @@
package com.dal.distributed.authentication;
+import com.dal.distributed.logger.model.EventLog;
import com.dal.distributed.main.OperationsMenu;
import com.dal.distributed.constant.AuthConstants;
import com.dal.distributed.logger.Logger;
@@ -16,27 +17,41 @@ public class Login {
public static Logger logger = Logger.instance();
- public void flow(Scanner sc) throws IOException {
+ public void flow(Scanner sc) throws Exception {
logger.info("For login, please provide your userId and press enter");
+ EventLog loginEvent = new EventLog();
+ loginEvent.setLogType("LOGIN");
String userId = sc.nextLine();
if (userId == null || userId.isEmpty()) {
+ loginEvent.setSuccess(false);
+ loginEvent.setUserId(userId);
+ EventLog.logEvent(loginEvent);
logger.info("Please type something before enter!");
return;
}
logger.info("Please provide your password and press enter");
String password = sc.nextLine();
if (password == null || password.isEmpty()) {
+ loginEvent.setSuccess(false);
+ loginEvent.setUserId(userId);
+ EventLog.logEvent(loginEvent);
logger.error("Password can't be empty!");
return;
}
Optional userOpt = AuthFileUtils.readUserDetails(AuthConstants.USER_DETAILS_FILE_LOCATION, getHashedValue(userId));
if(!userOpt.isPresent()) {
+ loginEvent.setSuccess(false);
+ loginEvent.setUserId(userId);
+ EventLog.logEvent(loginEvent);
logger.error("Either userId/password is not correct");
return;
}
UserRegistration user = userOpt.get();
String hashedPassword = getHashedValue(password);
if (!hashedPassword.equals(user.getPassword())) {
+ loginEvent.setSuccess(false);
+ loginEvent.setUserId(userId);
+ EventLog.logEvent(loginEvent);
logger.error("Either userId/password is not correct");
return;
}
@@ -46,13 +61,22 @@ public void flow(Scanner sc) throws IOException {
logger.info(securityQuestion.getQuestion());
String securingAnsByUser = sc.nextLine();
if (securingAnsByUser == null || securingAnsByUser.isEmpty()) {
+ loginEvent.setSuccess(false);
+ loginEvent.setUserId(userId);
+ EventLog.logEvent(loginEvent);
logger.error("Your security answer can't be empty!");
return;
}
if (!securingAnsByUser.equals(securityQuestion.getAnswer())) {
+ loginEvent.setSuccess(false);
+ loginEvent.setUserId(userId);
+ EventLog.logEvent(loginEvent);
logger.info("Invalid answer please try again!");
return;
}
+ loginEvent.setSuccess(true);
+ loginEvent.setUserId(userId);
+ EventLog.logEvent(loginEvent);
logger.info("You are successfully logged in!!");
OperationsMenu operationsMenu = new OperationsMenu();
operationsMenu.displayOperationsMenu(userId, sc);
diff --git a/src/main/java/com/dal/distributed/authentication/Registration.java b/src/main/java/com/dal/distributed/authentication/Registration.java
index 70f03dc..6a30bd8 100644
--- a/src/main/java/com/dal/distributed/authentication/Registration.java
+++ b/src/main/java/com/dal/distributed/authentication/Registration.java
@@ -4,6 +4,7 @@
import com.dal.distributed.logger.Logger;
import com.dal.distributed.authentication.model.SecurityQuestions;
import com.dal.distributed.authentication.model.UserRegistration;
+import com.dal.distributed.logger.model.EventLog;
import org.apache.commons.codec.digest.DigestUtils;
import java.util.ArrayList;
@@ -24,14 +25,19 @@ public class Registration {
public void registerUser() {
Scanner sc = new Scanner(System.in);
+ EventLog registerEvent = new EventLog();
+ registerEvent.setLogType("REGISTRATION");
String userId;
String password;
logger.info("Enter a UserID containing 5 to 15 characters: ");
userId = sc.nextLine();
+ registerEvent.setUserId(userId);
Boolean userIdValid = performUserIdValidations(userId);
if (!userIdValid) {
+ registerEvent.setSuccess(false);
+ EventLog.logEvent(registerEvent);
return;
}
@@ -39,24 +45,32 @@ public void registerUser() {
password = sc.nextLine();
Boolean isPasswordValid = performPasswordValidations(password);
if (!isPasswordValid) {
+ registerEvent.setSuccess(false);
+ EventLog.logEvent(registerEvent);
return;
}
logger.info(AuthConstants.SECURITY_QUESTION_1);
final String securityAnswerOne = sc.nextLine();
if (!validateSecurityInput(securityAnswerOne)) {
+ registerEvent.setSuccess(false);
+ EventLog.logEvent(registerEvent);
return;
}
logger.info(AuthConstants.SECURITY_QUESTION_2);
final String securityAnswerTwo = sc.nextLine();
if (!validateSecurityInput(securityAnswerTwo)) {
+ registerEvent.setSuccess(false);
+ EventLog.logEvent(registerEvent);
return;
}
logger.info(AuthConstants.SECURITY_QUESTION_3);
final String securityAnswerThree = sc.nextLine();
if (!validateSecurityInput(securityAnswerThree)) {
+ registerEvent.setSuccess(false);
+ EventLog.logEvent(registerEvent);
return;
}
@@ -73,7 +87,8 @@ public void registerUser() {
AuthFileUtils file = new AuthFileUtils();
file.writeUserDetails(AuthConstants.USER_DETAILS_FILE_LOCATION, user.toString());
-
+ registerEvent.setSuccess(true);
+ EventLog.logEvent(registerEvent);
logger.info("Registration completed successfully!!! You can now access the system with userID and Password.");
}
diff --git a/src/main/java/com/dal/distributed/constant/AuthConstants.java b/src/main/java/com/dal/distributed/constant/AuthConstants.java
index 6557976..223f15d 100644
--- a/src/main/java/com/dal/distributed/constant/AuthConstants.java
+++ b/src/main/java/com/dal/distributed/constant/AuthConstants.java
@@ -10,6 +10,12 @@ public final class AuthConstants {
public static final String USER_DETAILS_FILE_LOCATION = "usr/dpg9/authentication/User_Profile/";
+ public static final String AUTHENTICATION_FOLDER = "usr/dpg9/authentication/";
+
+ public static final String AUTHENTICATION_FILE = "User_Profile";
+
public static final String SUCCESS = "SUCCESS";
+ public static final String FAILURE = "FAILURE";
+
}
diff --git a/src/main/java/com/dal/distributed/constant/DataConstants.java b/src/main/java/com/dal/distributed/constant/DataConstants.java
index c0cc98d..7b001d3 100644
--- a/src/main/java/com/dal/distributed/constant/DataConstants.java
+++ b/src/main/java/com/dal/distributed/constant/DataConstants.java
@@ -8,4 +8,8 @@ public class DataConstants {
public static final String QUERY_LOGS_FILE_LOCATION = "usr/dpg9/logs/";
public static final String QUERY_LOG_FILE_NAME = "query_logs";
+
+ public static final String EVENT_LOG_FILE_NAME = "event_logs";
+
+ public static final String FILE_FORMAT = ".psv";
}
diff --git a/src/main/java/com/dal/distributed/constant/QueryRegex.java b/src/main/java/com/dal/distributed/constant/QueryRegex.java
index 7972f57..35e3914 100644
--- a/src/main/java/com/dal/distributed/constant/QueryRegex.java
+++ b/src/main/java/com/dal/distributed/constant/QueryRegex.java
@@ -6,8 +6,15 @@ public class QueryRegex {
public static final Pattern createDatabase = Pattern.compile("create\\s+database\\s+(\\w+)\\;", Pattern.CASE_INSENSITIVE);
public static final Pattern useDatabase = Pattern.compile("USE\\s+(\\w+)\\;", Pattern.CASE_INSENSITIVE);
public static final Pattern createTable = Pattern.compile("CREATE\\s+TABLE\\s+(\\w+)\\s*\\((.+)\\)\\;", Pattern.CASE_INSENSITIVE);
- public static final Pattern updateTable = Pattern.compile("UPDATE\\s+(\\w+)\\s+SET\\s+(\\w+\\=(\\w|\\'\\'|\\'\\w+\\'))\\s+(WHERE\\s+(\\w+\\s*(\\=|\\<|\\>|LIKE|\\<\\=|\\>\\=)\\s*(\\'\\w*\\'|\\w+)))?\\;", Pattern.CASE_INSENSITIVE);
- public static final Pattern deleteDataInTable = Pattern.compile("DELETE\\s+FROM\\s+(\\w+)\\s+WHERE\\s+(\\w+\\s*(\\=|\\<|\\>|LIKE|\\<\\=|\\>\\=)\\s*(\\'\\w*\\'|\\w+))\\;", Pattern.CASE_INSENSITIVE);
- public static final Pattern insertDataIntoTable = Pattern.compile("insert\\s+into\\s+(\\w+)((.+))?\\s+values\\s*\\((.+)\\);", Pattern.CASE_INSENSITIVE);
- public static final Pattern selectDataFromTable = Pattern.compile("select\\s+((\\*)|(\\w+)|(\\w+\\,\\s*)+\\w+)\\s+from\\s+\\w+\\s*(where\\s+(\\w+)\\s*(\\=|LIKE|IN|\\<|\\>|\\!\\=|\\<\\=|\\>\\=)\\s*(\\d+|\\'\\w+\\'))?\\;", Pattern.CASE_INSENSITIVE);
+ public static final Pattern updateTable = Pattern.compile("UPDATE\\s+(\\w+)\\s+SET\\s+(\\w+\\=(\\w|\\'\\'|\\'\\w+\\'))\\s+(WHERE\\s+(\\w+\\s*(\\=|\\<|\\>|\\<\\=|\\>\\=)\\s*(\\'\\w*\\'|\\w+)))?\\;", Pattern.CASE_INSENSITIVE);
+ public static final Pattern deleteDataInTable = Pattern.compile("DELETE\\s+FROM\\s+(\\w+)\\s+WHERE\\s+(\\w+\\s*(\\=|\\<|\\>|\\<\\=|\\>\\=)\\s*(\\'\\w*\\'|\\w+))\\;\\s*$", Pattern.CASE_INSENSITIVE);
+ public static final Pattern insertDataIntoTable = Pattern.compile("insert\\s+into\\s+(\\w+)((.+))?\\s+values\\s*\\((.+)\\);\\s*$", Pattern.CASE_INSENSITIVE);
+ public static final Pattern selectDataFromTable = Pattern.compile("select\\s+((\\*)|(\\w+)|(\\w+\\,\\s*)+\\w+)\\s+from\\s+(\\w+)\\s*(where\\s+(\\w+)\\s*(\\=|\\<|\\>|\\!\\=|\\<\\=|\\>\\=)\\s*(\\d+|\\'\\w+\\'))?\\;$", Pattern.CASE_INSENSITIVE);
+ public static final Pattern startTransaction = Pattern.compile("^start\\s+transaction;\\s*$", Pattern.CASE_INSENSITIVE);
+ public static final Pattern endTransaction = Pattern.compile("^(end\\s+transaction)|(commit);\\s*$", Pattern.CASE_INSENSITIVE);
+ public static final Pattern valueBetweenQuotes = Pattern.compile("(?<=\").*?(?=\")");
+ public static final Pattern countQueriesAnalytics = Pattern.compile("count\\s+queries\\s+by\\s+(.*)for\\s+(.*)", Pattern.CASE_INSENSITIVE);
+
+ public static final Pattern digitOnlyRegex = Pattern.compile("^[0-9]+$");
+
}
\ No newline at end of file
diff --git a/src/main/java/com/dal/distributed/constant/QueryTypes.java b/src/main/java/com/dal/distributed/constant/QueryTypes.java
index ec2ea96..d79e093 100644
--- a/src/main/java/com/dal/distributed/constant/QueryTypes.java
+++ b/src/main/java/com/dal/distributed/constant/QueryTypes.java
@@ -8,4 +8,6 @@ public class QueryTypes {
public static final String DELETE = "DELETE";
public static final String INSERT = "INSERT";
public static final String SELECT = "SELECT";
+ public static final String START_TRANSACTION = "START_TRANSACTION";
+ public static final String END_TRANSACTION = "END_TRANSACTION";
}
diff --git a/src/main/java/com/dal/distributed/constant/VMConstants.java b/src/main/java/com/dal/distributed/constant/VMConstants.java
new file mode 100644
index 0000000..ddad919
--- /dev/null
+++ b/src/main/java/com/dal/distributed/constant/VMConstants.java
@@ -0,0 +1,15 @@
+package com.dal.distributed.constant;
+
+public class VMConstants {
+ public static final String projectPath = "/home/chanpreets10/csci-5408-group-project-dpg9/";
+ public static final String USERNAME = "chanpreets10";
+ public static final int port = 22;
+ public static final String KEYNAME = "";
+// public static final String PRIVATE_KEY = projectPath + "ssh-keys/" + KEYNAME;
+ public static final String PRIVATE_KEY = projectPath + "ssh-keys/chanpreets10" + KEYNAME;
+ public static final String EXTERNAL_IP = "";
+ public static final String LOCAL="local";
+ public static final String REMOTE="remote";
+// VM-1 : 34.132.74.189
+// VM-2 :
+}
diff --git a/src/main/java/com/dal/distributed/export/ExportDatabase.java b/src/main/java/com/dal/distributed/export/ExportDatabase.java
new file mode 100644
index 0000000..dd5d219
--- /dev/null
+++ b/src/main/java/com/dal/distributed/export/ExportDatabase.java
@@ -0,0 +1,323 @@
+package com.dal.distributed.export;
+
+import com.dal.distributed.constant.DataConstants;
+import com.dal.distributed.constant.MiscConstants;
+import com.dal.distributed.constant.VMConstants;
+import com.dal.distributed.logger.Logger;
+import com.dal.distributed.main.model.Column;
+import com.dal.distributed.main.model.Table;
+import com.dal.distributed.utils.DatabaseUtils;
+import com.dal.distributed.utils.FileOperations;
+import com.dal.distributed.utils.RemoteVmUtils;
+
+import java.io.*;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class ExportDatabase {
+
+ private static Logger logger = Logger.instance();
+
+ private static final String DEFAULT_EXPORT_FILE_LOCATION = "usr/dpg9/output/export/";
+
+ private static final String DEFAULT_EXPORT_FILE_NAME = "%s_%s.sql";
+
+ private static final String INSERT_GENERIC_QUERY_PREFIX = "INSERT INTO %s VALUES ";
+
+ private static final String CREATE_DATABASE_QUERY_PREFIX = "CREATE DATABASE IF NOT EXISTS %s;";
+
+ private static final String USE_DATABASE = "USE %s;";
+
+ private static final String EXPORT_OUTPUT_PROMPT = "Your exported file will be found at: %s";
+
+ public void flow(Scanner sc) throws Exception {
+ while (true) {
+ logger.info("Please choose any one of the following options:");
+ logger.info("\n1. Show Databases list");
+ logger.info("2. Export Database");
+ logger.info("3. Go back to main menu");
+ String option = sc.nextLine();
+
+ switch (option) {
+ case "1":
+ displayDatabases();
+ break;
+ case "2":
+ logger.info("Please choose a database");
+ String databaseName = sc.nextLine();
+ String fileName = exportStructureAndValue(databaseName);
+ if (fileName != null)
+ logger.info(String.format(EXPORT_OUTPUT_PROMPT, DEFAULT_EXPORT_FILE_LOCATION + fileName));
+ break;
+ case "3":
+ break;
+ default:
+ logger.error("Please choose a valid input!");
+ }
+
+ if("3".equals(option))
+ break;
+ }
+ }
+
+ private void displayDatabases() {
+ File[] files = FileOperations.readFiles(DataConstants.DATABASES_FOLDER_LOCATION);
+ List databaseNames = new ArrayList<>();
+ for (File file: files) {
+ if(file.isDirectory())
+ databaseNames.add(file.getName());
+ }
+ Collections.sort(databaseNames);
+ databaseNames.stream().forEach(logger::info);
+ }
+
+ private String exportStructureAndValue(String database) throws Exception {
+ if (!isDatabaseExists(database))
+ return null;
+ List schemaFiles = DatabaseUtils.getTableSchemaFiles(database);
+ List remoteTables = DatabaseUtils.getRemoteTables(database);
+ if ((schemaFiles == null || schemaFiles.isEmpty()) && (remoteTables == null || remoteTables.isEmpty())) {
+ logger.info("Selected database is empty! Please choose another one to export");
+ return null;
+ }
+ List tables = new ArrayList<>(remoteTables);
+ if (schemaFiles != null || !schemaFiles.isEmpty()) {
+ System.out.println("Going in if block");
+ for (File tableFile: schemaFiles) {
+ System.out.println("Local schema file: " + tableFile.getName());
+ List columnDefs = DatabaseUtils.getColumnDefinitions(database, tableFile);
+ Table table = Table.createTableModel(tableFile.getName(), database, columnDefs);
+ tables.add(table);
+ System.out.println("Table model created for: " + tableFile.getName() + "is: "+ table.getTableName());
+ }
+ }
+ System.out.println("All tables remote and local:");
+ tables.stream().forEach(x -> {
+ System.out.println(x.getTableName());
+ });
+
+ //sort tables based on the foreign keys
+ Collections.sort(tables, (o1, o2) -> {
+ if (o1.getTableName().equals(o2.getTableName()))
+ return 0;
+ List o1Columns = o1.getColumns();
+ for (Column o1Column : o1Columns) {
+ List constraints = o1Column.getConstraints();
+ if (constraints == null || constraints.isEmpty())
+ continue;
+ for (String constraint: constraints) {
+ if (constraint.contains(o2.getTableName()))
+ return 1;
+ }
+ }
+ return -1;
+ });
+
+ System.out.println("All tables after sorting remote and local:");
+ tables.stream().forEach(x -> {
+ System.out.println(x.getTableName());
+ });
+ return exportDataToSqlFile(database, tables);
+ }
+
+ private boolean isDatabaseExists(String databaseName) {
+ File[] databases = FileOperations.readFiles(DataConstants.DATABASES_FOLDER_LOCATION);
+ boolean isExist=false;
+ for (File file : databases) {
+ if (file.getName().equalsIgnoreCase(databaseName)) {
+ isExist=true;
+ }
+ }
+ if(!isExist){
+ logger.error("Error Code: 1007. Can't export database '" + databaseName + "'; Database doesn't exists.");
+ return false;
+ }
+ return true;
+ }
+
+ private String exportDataToSqlFile(String database, List tables) throws Exception {
+ FileOperations.createNewFolderRecursively(DEFAULT_EXPORT_FILE_LOCATION);
+ String fileName = String.format(DEFAULT_EXPORT_FILE_NAME, new Date().getTime(), database);
+ File exportSqlFile = new File(DEFAULT_EXPORT_FILE_LOCATION + File.separator + fileName);
+ try ( FileWriter fw = new FileWriter(exportSqlFile);
+ BufferedWriter bw = new BufferedWriter(fw);){
+ bw.write(String.format(CREATE_DATABASE_QUERY_PREFIX, database));
+ bw.write("\n");
+ bw.write(String.format(USE_DATABASE, database));
+ bw.write("\n");
+ for (Table table: tables) {
+ String tableLocation = DatabaseUtils.getTableLocation(database, table.getTableName());
+ System.out.println(table.getTableName() + " is in: " + tableLocation);
+ boolean isLocal = !VMConstants.REMOTE.equals(tableLocation);
+ System.out.println(table.getTableName() + " is in local: " + isLocal);
+ String tableQueries = generateCreateTableAlongWithData(database, table, isLocal);
+ bw.write(tableQueries);
+ bw.write("\n");
+ }
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ return fileName;
+ }
+
+
+ private String generateCreateTableAlongWithData(String database, Table table, boolean isLocal) throws Exception {
+ String createTableQuery = generateCreateTable(database, table);
+ String insertQueries = isLocal? generateInsertData(database, table): generateInsertDataForRemoteTable(database, table);
+ StringBuilder createAndInsertQueriesTable = new StringBuilder(createTableQuery);
+ createAndInsertQueriesTable.append("\n");
+ createAndInsertQueriesTable.append(insertQueries);
+ return createAndInsertQueriesTable.toString();
+ }
+
+ private String generateInsertDataForRemoteTable(String database, Table table) throws Exception {
+ String dataFilePath = DatabaseUtils.getDataFilePathFromTable(database, table.getTableName());
+ String data = RemoteVmUtils.readFileContent(VMConstants.projectPath + dataFilePath);
+ List rowsWithHeader = Arrays.asList(data.split("\n"));
+ List columnNames = table.getColumns().stream()
+ .map(Column::getColumnName).collect(Collectors.toList());
+ Map columnNameToColumn = table.getColumns().stream()
+ .collect(Collectors.toMap(Column::getColumnName, Function.identity()));
+ if (rowsWithHeader.size() == 1)
+ return "\n";
+ String genericInsertQueryPrefix = String.format(INSERT_GENERIC_QUERY_PREFIX, table.getTableName());
+ StringBuilder insertQueryBuilder = new StringBuilder(genericInsertQueryPrefix);
+ for (int i=1; i;
+ StringBuilder createTableQueryBuilder = new StringBuilder();
+ createTableQueryBuilder.append(String.format("CREATE TABLE IF NOT EXISTS %s.%s", database, table.getTableName()));
+ createTableQueryBuilder.append("(");
+ createTableQueryBuilder.append("\n");
+ createTableQueryBuilder.append(generateColumnDefinitionQuery(table));
+ createTableQueryBuilder.append("\n");
+ createTableQueryBuilder.append(");");
+ return createTableQueryBuilder.toString();
+ }
+
+ private String generateColumnDefinitionQuery(Table table) {
+ StringBuilder columnDefinitions = new StringBuilder();
+ for (Column column: table.getColumns()) {
+ columnDefinitions.append("\t");
+ columnDefinitions.append(column.getColumnName());
+ columnDefinitions.append(" ");
+ columnDefinitions.append(column.getDataType());
+ columnDefinitions.append(" ");
+ boolean fkConstraint = false;
+ if (column.getConstraints() != null && !column.getConstraints().isEmpty()) {
+ String constraints = column.getConstraints()
+ .stream()
+ .filter(constraint -> !constraint.contains("FOREIGN KEY"))
+ .collect(Collectors.joining(" "));
+ fkConstraint = column.getConstraints()
+ .stream()
+ .anyMatch(constraint -> constraint.contains("FOREIGN KEY"));
+ columnDefinitions.append(constraints);
+ }
+ columnDefinitions.append(",\n");
+ if (fkConstraint) {
+ String fkConstraintStr = column.getConstraints().stream().filter(constraint -> constraint.contains("FOREIGN KEY")).findAny().get();
+ columnDefinitions.append("\t");
+ columnDefinitions.append(getForeignKeyConstraint(fkConstraintStr, column.getColumnName()));
+ columnDefinitions.append(",\n");
+ }
+ }
+ columnDefinitions.deleteCharAt(columnDefinitions.length()-1);
+ columnDefinitions.deleteCharAt(columnDefinitions.length()-1);
+ return columnDefinitions.toString();
+ }
+
+ private String getForeignKeyConstraint(String fkConstraint, String columnName) {
+ String [] fkSplit = fkConstraint.split(" ");
+ StringBuilder fkConstraintCode = new StringBuilder();
+ for (int i=0; i columnNames = DatabaseUtils.getColumnNames(dataFile);
+ Map columnNameToColumn = table.getColumns().stream()
+ .collect(Collectors.toMap(Column::getColumnName, Function.identity()));
+ String genericInsertQueryPrefix = String.format(INSERT_GENERIC_QUERY_PREFIX, table.getTableName());
+ boolean isDataPresent = false;
+ try (FileReader fr = new FileReader(dataFile);
+ BufferedReader br = new BufferedReader(fr);) {
+ // Buffered reader will now point after the header row
+ br.readLine();
+ String line;
+ // This builds the entire insert query
+ StringBuilder dataQueryBuilder = new StringBuilder(genericInsertQueryPrefix);
+ while ((line = br.readLine()) != null) {
+ isDataPresent = true;
+ String [] rowData = line.split(MiscConstants.PIPE);
+ //This builds only comma separated list for a single row.
+ StringBuilder rowDataBuilder = new StringBuilder("(");
+ for (int i=0; i columnNames, Map columnNameToColumn) {
+ StringBuilder rowDataBuilder = new StringBuilder("(");
+ for (int i=0; i transactionQueries = new ArrayList<>();
Logger logger = Logger.instance();
public void displayOperationsMenu(String userId, Scanner scanner) throws Exception {
while (true) {
- logger.info("Please choose from the following options:");
- logger.info("\n1. Write Queries");
+ logger.info("\nPlease choose from the following options:");
+ logger.info("1. Write Queries");
logger.info("2. Generate ERD");
logger.info("3. Export");
logger.info("4. Analytics");
@@ -32,15 +40,21 @@ public void displayOperationsMenu(String userId, Scanner scanner) throws Excepti
case "2":
break;
case "3":
+ ExportDatabase export = new ExportDatabase();
+ export.flow(scanner);
break;
case "4":
+ Analytics analytics = new Analytics();
+ analytics.analyze(scanner);
break;
case "5":
+ Main.databaseName = "";
break;
default:
logger.error("Please choose valid option!");
}
if ("5".equals(userInput)) {
+ EventLog.logLogoutEvent(userId);
logger.info("You are logged out");
break;
}
@@ -56,47 +70,148 @@ public void implementQuery(Scanner sc, String userId) throws Exception {
SelectQuery selectQuery = new SelectQuery();
UpdateTable updateTable = new UpdateTable();
DeleteDataFromTable deleteDataFromTable = new DeleteDataFromTable();
+ do {
+ logger.info("Write query for selected option:");
+ String query = sc.nextLine();
- logger.info("Write query for selected option:");
- String query = sc.nextLine();
-
- QueryLog logQuery = new QueryLog();
- logQuery.setFlag("valid");
- logQuery.setQuery(query);
- logQuery.setSubmissionTimestamp(String.valueOf(new Timestamp(System.currentTimeMillis())));
- logQuery.setSubmittedBy(userId);
-
- Map queryValidatorResults = queryExecutorObj.validateQuery(query);
+ QueryLog logQuery = new QueryLog();
+ logQuery.setFlag("valid");
+ logQuery.setQuery(query);
+ logQuery.setSubmissionTimestamp(String.valueOf(new Timestamp(System.currentTimeMillis())));
+ logQuery.setSubmittedBy(userId);
- if (((boolean) queryValidatorResults.get("isValidate")) && (queryValidatorResults.get("queryType") == QueryTypes.CREATE_DATABASE)) {
- if (createDatabase.execute(query)) {
- logger.info("Action: " + query + "\nMessage: 1 row(s) affected.\n");
+ Map queryValidatorResults = queryExecutorObj.validateQuery(query);
+ if (((boolean) queryValidatorResults.get("isValidate"))
+ && (queryValidatorResults.get("queryType") == QueryTypes.CREATE_DATABASE)) {
+ EventLog createDbEvent = new EventLog("CREATE_DB", userId);
+ logQuery.setOperation(QueryTypes.CREATE_DATABASE);
+ logQuery.setDatabaseName((String) queryValidatorResults.get("entity"));
+ Pair res = createDatabase.execute(query);
+ createDbEvent.setSuccess(res.getFirst());
+ createDbEvent.setDatabaseName(res.getSecond());
+ if (res.getFirst()) {
+ logger.info("Action: " + query + "\nMessage: 1 row(s) affected.\n");
+ }
+ EventLog.logEvent(createDbEvent);
+ } else if (((boolean) queryValidatorResults.get("isValidate"))
+ && (queryValidatorResults.get("queryType") == QueryTypes.USE)) {
+ logQuery.setOperation(QueryTypes.USE);
+ logQuery.setDatabaseName((String) queryValidatorResults.get("entity"));
+ if (useDatabase.execute(query)) {
+ logger.info("Action: " + query + "\nMessage: 0 row(s) affected.\n");
+ } else {
+ logger.info("Database doesn't exist");
+ }
+ } else if (((boolean) queryValidatorResults.get("isValidate"))
+ && (queryValidatorResults.get("queryType") == QueryTypes.CREATE_TABLE)) {
+ EventLog createTableEvent = new EventLog("CREATE_TABLE", userId);
+ if (Main.databaseName == null || Main.databaseName.isEmpty()) {
+ logger.error("Please select database first");
+ }
+ createTableEvent.setDatabaseName(Main.databaseName);
+ logQuery.setOperation(QueryTypes.CREATE_TABLE);
+ logQuery.setTableName((String) queryValidatorResults.get("entity"));
+ OperationStatus result = createTable.execute(query);
+ createTableEvent.setSuccess(result.isStatus());
+ createTableEvent.setTableName(logQuery.getTableName());
+ if (result.isStatus()) {
+ logger.info("Action: " + query + "\nMessage: 0 row(s) affected.\n");
+ }
+ logQuery.setDatabaseName(result.getDatabaseName());
+ EventLog.logEvent(createTableEvent);
+ } else if (((boolean) queryValidatorResults.get("isValidate"))
+ && (queryValidatorResults.get("queryType") == QueryTypes.INSERT)) {
+ logQuery.setOperation(QueryTypes.INSERT);
+ logQuery.setTableName((String) queryValidatorResults.get("entity"));
+ if (Main.databaseName == null || Main.databaseName.isEmpty()) {
+ logger.error("Please select database first");
+ } else if (Main.isTransaction) {
+ transactionQueries.add(insertIntoTable.execute(query));
+ } else {
+ OperationStatus result = insertIntoTable.execute(query);
+ if (result != null && result.isStatus()) {
+ logger.info("Action: " + query + "\nMessage: 1 row(s) affected.\n");
+ logQuery.setDatabaseName(result.getDatabaseName());
+ } else {
+ logger.error("Required table/columns/data does not exist");
+ }
+ }
+ } else if (((boolean) queryValidatorResults.get("isValidate"))
+ && (queryValidatorResults.get("queryType") == QueryTypes.SELECT)) {
+ logQuery.setOperation(QueryTypes.SELECT);
+ logQuery.setTableName((String) queryValidatorResults.get("entity"));
+ if (Main.databaseName == null || Main.databaseName.isEmpty()) {
+ logger.error("Please select database first");
+ } else if (Main.isTransaction) {
+ transactionQueries.add(selectQuery.execute(query));
+ } else {
+ OperationStatus result = selectQuery.execute(query);
+ if (result != null && result.isStatus()) {
+ logQuery.setDatabaseName(result.getDatabaseName());
+ } else {
+ logger.error("Required table/columns/data does not exist");
+ }
+ }
+ } else if (((boolean) queryValidatorResults.get("isValidate"))
+ && (queryValidatorResults.get("queryType") == QueryTypes.UPDATE)) {
+ logQuery.setOperation(QueryTypes.UPDATE);
+ logQuery.setTableName((String) queryValidatorResults.get("entity"));
+ if (Main.databaseName == null || Main.databaseName.isEmpty()) {
+ logger.error("Please select database first");
+ } else if (Main.isTransaction) {
+ transactionQueries.add(updateTable.execute(query));
+ } else {
+ OperationStatus result = updateTable.execute(query);
+ if (result != null && result.isStatus()) {
+ logger.info("Action: " + query + "\nMessage: " + result.getCount() + " row(s) affected.\n");
+ logQuery.setDatabaseName(result.getDatabaseName());
+ } else {
+ logger.error("Required table/columns/data does not exist");
+ }
+ }
+ } else if (((boolean) queryValidatorResults.get("isValidate"))
+ && (queryValidatorResults.get("queryType") == QueryTypes.DELETE)) {
+ logQuery.setOperation(QueryTypes.DELETE);
+ logQuery.setTableName((String) queryValidatorResults.get("entity"));
+ if (Main.databaseName == null || Main.databaseName.isEmpty()) {
+ logger.error("Please select database first");
+ } else if (Main.isTransaction) {
+ transactionQueries.add(deleteDataFromTable.execute(query));
+ } else {
+ OperationStatus result = deleteDataFromTable.execute(query);
+ if (result != null && result.isStatus()) {
+ logger.info("Action: " + query + "\nMessage: " + result.getCount() + " row(s) affected.\n");
+ logQuery.setDatabaseName(result.getDatabaseName());
+ } else {
+ logger.error("Required table/columns/data does not exist");
+ }
+ }
+ } else if (((boolean) queryValidatorResults.get("isValidate"))
+ && (queryValidatorResults.get("queryType") == QueryTypes.START_TRANSACTION)) {
+ if (Main.databaseName == null || Main.databaseName.isEmpty()) {
+ logger.error("Please select database first");
+ } else {
+ logQuery.setOperation(QueryTypes.START_TRANSACTION);
+ Main.isTransaction = true;
+ }
+ } else if (((boolean) queryValidatorResults.get("isValidate"))
+ && (queryValidatorResults.get("queryType") == QueryTypes.END_TRANSACTION)) {
+ logQuery.setOperation(QueryTypes.END_TRANSACTION);
+ TransactionProcessing transactionProcessing = new TransactionProcessing();
+ for (int i = 0; i < transactionQueries.size(); i++) {
+ for (int j = i + 1; j < transactionQueries.size(); j++) {
+ if (transactionQueries.get(i).getTableName().equals(transactionQueries.get(j).getTableName())) {
+ transactionQueries.get(j).setRepeatTable(true);
+ }
+ }
+ }
+ transactionProcessing.execute(transactionQueries);
+ } else {
+ logQuery.setFlag("invalid");
+ logger.error("Oops.. looks like I encountered error in parsing query");
}
- } else if (((boolean) queryValidatorResults.get("isValidate")) && (queryValidatorResults.get("queryType") == QueryTypes.USE)) {
- if (useDatabase.execute(query)) {
- logger.info("Action: " + query + "\nMessage: 0 row(s) affected.\n");
- }
- } else if (((boolean) queryValidatorResults.get("isValidate")) && (queryValidatorResults.get("queryType") == QueryTypes.CREATE_TABLE)) {
- if (createTable.execute(query)) {
- logger.info("Action: " + query + "\nMessage: 0 row(s) affected.\n");
- }
- } else if (((boolean) queryValidatorResults.get("isValidate")) && (queryValidatorResults.get("queryType") == QueryTypes.INSERT)) {
- insertIntoTable.execute(query);
- } else if (((boolean) queryValidatorResults.get("isValidate")) && (queryValidatorResults.get("queryType") == QueryTypes.SELECT)) {
- selectQuery.execute(query);
- } else if (((boolean) queryValidatorResults.get("isValidate")) && (queryValidatorResults.get("queryType") == QueryTypes.UPDATE)) {
- if (updateTable.execute(query)) {
- logger.info("Action: " + query + "\nMessage: 1 row(s) affected.\n");
- }
- } else if (((boolean) queryValidatorResults.get("isValidate")) && (queryValidatorResults.get("queryType") == QueryTypes.DELETE)) {
- if (deleteDataFromTable.execute(query)) {
- logger.info("Action: " + query + "\nMessage: 1 row(s) affected.\n");
- }
- } else {
- logQuery.setFlag("invalid");
- logger.error("Oops.. looks like I encountered error in parsing query");
- }
- FileOperations.writeToExistingFile(logQuery.toString(),
- DataConstants.QUERY_LOG_FILE_NAME, DataConstants.QUERY_LOGS_FILE_LOCATION);
+ FileOperations.writeToExistingFile(logQuery.toString(),
+ DataConstants.QUERY_LOG_FILE_NAME, DataConstants.QUERY_LOGS_FILE_LOCATION);
+ } while (Main.isTransaction);
}
}
diff --git a/src/main/java/com/dal/distributed/main/model/Column.java b/src/main/java/com/dal/distributed/main/model/Column.java
new file mode 100644
index 0000000..67804a0
--- /dev/null
+++ b/src/main/java/com/dal/distributed/main/model/Column.java
@@ -0,0 +1,51 @@
+package com.dal.distributed.main.model;
+
+import com.dal.distributed.constant.MiscConstants;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class Column {
+
+ private String columnName;
+
+ private String dataType;
+
+ private List constraints;
+
+ public String getColumnName() {
+ return columnName;
+ }
+
+ public void setColumnName(String columnName) {
+ this.columnName = columnName;
+ }
+
+ public String getDataType() {
+ return dataType;
+ }
+
+ public void setDataType(String dataType) {
+ this.dataType = dataType;
+ }
+
+ public List getConstraints() {
+ return constraints;
+ }
+
+ public void setConstraints(List constraints) {
+ this.constraints = constraints;
+ }
+
+ public static Column createColumnModel(String columnDef) {
+ String [] columnsDefSplit = columnDef.split(MiscConstants.PIPE);
+ Column column = new Column();
+ column.setColumnName(columnsDefSplit[0]);
+ column.setDataType(columnsDefSplit[1]);
+ if (columnsDefSplit.length > 2) {
+ List columnDefList = Arrays.asList(columnsDefSplit);
+ column.setConstraints(columnDefList.subList(2, columnDefList.size()));
+ }
+ return column;
+ }
+}
diff --git a/src/main/java/com/dal/distributed/main/model/Pair.java b/src/main/java/com/dal/distributed/main/model/Pair.java
new file mode 100644
index 0000000..33275f8
--- /dev/null
+++ b/src/main/java/com/dal/distributed/main/model/Pair.java
@@ -0,0 +1,33 @@
+package com.dal.distributed.main.model;
+
+public class Pair {
+
+ private T first;
+
+ private V second;
+
+ public Pair() {
+
+ }
+
+ public Pair(T first, V second) {
+ this.first = first;
+ this.second = second;
+ }
+
+ public T getFirst() {
+ return first;
+ }
+
+ public void setFirst(T first) {
+ this.first = first;
+ }
+
+ public V getSecond() {
+ return second;
+ }
+
+ public void setSecond(V second) {
+ this.second = second;
+ }
+}
diff --git a/src/main/java/com/dal/distributed/main/model/Table.java b/src/main/java/com/dal/distributed/main/model/Table.java
new file mode 100644
index 0000000..1d7b9db
--- /dev/null
+++ b/src/main/java/com/dal/distributed/main/model/Table.java
@@ -0,0 +1,69 @@
+package com.dal.distributed.main.model;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+public class Table implements Comparator {
+
+ private String tableName;
+
+ private String databaseName;
+
+ private List columns;
+
+ public String getTableName() {
+ return tableName;
+ }
+
+ public void setTableName(String tableName) {
+ this.tableName = tableName;
+ }
+
+ public String getDatabaseName() {
+ return databaseName;
+ }
+
+ public void setDatabaseName(String databaseName) {
+ this.databaseName = databaseName;
+ }
+
+ public List getColumns() {
+ return columns;
+ }
+
+ public void setColumns(List columns) {
+ this.columns = columns;
+ }
+
+ public static Table createTableModel(String tableName, String databaseName, List columnDefs) {
+ Table table = new Table();
+ table.setDatabaseName(databaseName);
+ //to remove .psv with the table name
+ table.setTableName(tableName.split("_")[0]);
+ List columns = new ArrayList<>();
+ for (String columnDef: columnDefs) {
+ Column col = Column.createColumnModel(columnDef);
+ columns.add(col);
+ }
+ table.setColumns(columns);
+ return table;
+ }
+
+ @Override
+ public int compare(Table o1, Table o2) {
+ if (o1.getTableName().equals(o2.getTableName()))
+ return 0;
+ List o1Columns = o1.getColumns();
+ for (Column o1Column : o1Columns) {
+ List constraints = o1Column.getConstraints();
+ if(constraints == null || constraints.isEmpty())
+ continue;
+ for (String constraint: constraints) {
+ if (constraint.contains(o2.getTableName()))
+ return 1;
+ }
+ }
+ return -1;
+ }
+}
diff --git a/src/main/java/com/dal/distributed/miscellaneous/MiscOperations.java b/src/main/java/com/dal/distributed/miscellaneous/MiscOperations.java
index c43331a..b250236 100644
--- a/src/main/java/com/dal/distributed/miscellaneous/MiscOperations.java
+++ b/src/main/java/com/dal/distributed/miscellaneous/MiscOperations.java
@@ -1,13 +1,20 @@
package com.dal.distributed.miscellaneous;
-import com.dal.distributed.constant.MiscConstants;
+import com.dal.distributed.constant.AuthConstants;
+import com.dal.distributed.constant.DataConstants;
import com.dal.distributed.utils.FileOperations;
import java.io.IOException;
public class MiscOperations {
public static void createInitFolders() throws IOException {
- FileOperations.createNewFolderRecursively(MiscConstants.initFolder);
- FileOperations.createNewFolderRecursively(MiscConstants.initFolder2);
+ FileOperations.createNewFolderRecursively(AuthConstants.AUTHENTICATION_FOLDER);
+ FileOperations.createNewFolderRecursively(DataConstants.LOGS_FILE_LOCATION);
+ FileOperations.createNewFolderRecursively(DataConstants.DATABASES_FOLDER_LOCATION);
+ }
+
+ public static void createUserProfileFile() throws IOException {
+ FileOperations.createNewFile(AuthConstants.AUTHENTICATION_FOLDER,
+ AuthConstants.AUTHENTICATION_FILE);
}
}
diff --git a/src/main/java/com/dal/distributed/queryImpl/CreateDatabase.java b/src/main/java/com/dal/distributed/queryImpl/CreateDatabase.java
index f8a29de..b9d6666 100644
--- a/src/main/java/com/dal/distributed/queryImpl/CreateDatabase.java
+++ b/src/main/java/com/dal/distributed/queryImpl/CreateDatabase.java
@@ -1,33 +1,42 @@
package com.dal.distributed.queryImpl;
-import java.io.File;
-import java.io.IOException;
-
import com.dal.distributed.constant.DataConstants;
import com.dal.distributed.logger.Logger;
+import com.dal.distributed.main.model.Pair;
import com.dal.distributed.utils.FileOperations;
+import com.dal.distributed.utils.RemoteVmUtils;
+
+import java.io.File;
public class CreateDatabase {
Logger logger = Logger.instance();
- public boolean execute(String query) throws IOException {
+ public Pair execute(String query) throws Exception {
+ Pair createDbRes = new Pair<>();
+ createDbRes.setFirst(false);
String[] sql = query.split("\\s+");
if (sql[0].equalsIgnoreCase("create") && sql[1].equalsIgnoreCase("database")) {
- //Remove the semicolon from database name
String databaseName = sql[2].substring(0, sql[2].length() - 1).toLowerCase();
+ createDbRes.setSecond(databaseName);
File[] databases = FileOperations.readFiles(DataConstants.DATABASES_FOLDER_LOCATION);
for (File file : databases) {
if (file.getName().equalsIgnoreCase(databaseName)) {
logger.error("Error Code: 1007. Can't create database '" + databaseName + "'; Database exists.");
- return false;
+ return createDbRes;
}
}
FileOperations.createNewFolder(DataConstants.DATABASES_FOLDER_LOCATION, databaseName);
- //FileOperations.writeToExistingFile(databaseName+"|","databases.psv", DataConstants.LOGS_FILE_LOCATION);
- return true;
- } else
- return false;
+ FileOperations.writeToExistingFile("tablename|location", databaseName+".psv", DataConstants.DATABASES_FOLDER_LOCATION);
+ FileOperations.writeToExistingFile(databaseName + "|", "databases.psv", DataConstants.DATABASES_FOLDER_LOCATION);
+
+ RemoteVmUtils.createNewFolder(DataConstants.DATABASES_FOLDER_LOCATION, databaseName);
+ RemoteVmUtils.writeToExistingFile(databaseName + "|", "databases.psv", DataConstants.DATABASES_FOLDER_LOCATION);
+ RemoteVmUtils.writeToExistingFile("tablename|location", databaseName+".psv", DataConstants.DATABASES_FOLDER_LOCATION);
+ createDbRes.setFirst(true);
+ return createDbRes;
+ } else
+ return createDbRes;
}
}
\ No newline at end of file
diff --git a/src/main/java/com/dal/distributed/queryImpl/CreateTable.java b/src/main/java/com/dal/distributed/queryImpl/CreateTable.java
index 5032997..50613db 100644
--- a/src/main/java/com/dal/distributed/queryImpl/CreateTable.java
+++ b/src/main/java/com/dal/distributed/queryImpl/CreateTable.java
@@ -1,38 +1,97 @@
package com.dal.distributed.queryImpl;
import com.dal.distributed.constant.DataConstants;
+import com.dal.distributed.constant.VMConstants;
+import com.dal.distributed.logger.Logger;
import com.dal.distributed.main.Main;
+import com.dal.distributed.queryImpl.model.OperationStatus;
+import com.dal.distributed.utils.DatabaseUtils;
import com.dal.distributed.utils.FileOperations;
+import com.dal.distributed.utils.RemoteVmUtils;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+
+import java.io.File;
+import java.io.IOException;
public class CreateTable {
- public boolean execute(String query) {
-
- String[] sql = query.split("\\s+");
- if(sql.length>3&& sql[0].toLowerCase().equals("create")&&sql[1].toLowerCase().equals("table"))
- {
- String mainStatement=query.substring(query.indexOf(sql[2]));
- String tableName=mainStatement.substring(0,mainStatement.indexOf("("));
- String schema=mainStatement.substring(mainStatement.indexOf("(")+1,mainStatement.indexOf(";")-1);
- String columnNames="";
- String[] columns= schema.split(",");
- int i=0;
- for(String col:columns)
- {
- columnNames+=col.substring(0,col.indexOf(" "));
- if(i!=columns.length-1)
- columnNames+="|";
- i++;
- }
- schema=schema.replaceAll(",", "|");
- FileOperations.writeToExistingFile(columnNames, tableName+".psv", DataConstants.DATABASES_FOLDER_LOCATION+Main.databaseName+"/");
- FileOperations.writeToExistingFile(schema, tableName+"_Schema"+".psv", DataConstants.DATABASES_FOLDER_LOCATION+Main.databaseName+"/");
- //FileOperations.writeToExistingFile(tableName+"|", Main.databaseName+".psv", DataConstants.LOGS_FILE_LOCATION);
- return true;
+
+ private static Logger logger = Logger.instance();
+
+ public OperationStatus execute(String query) throws Exception {
+ if (Main.databaseName == null || Main.databaseName.isEmpty()) {
+ System.out.println("No database selected");
+ return new OperationStatus(Boolean.FALSE, null);
}
+ int min = 0, max = 1;
+ String location = "";
+ int randomNum = ThreadLocalRandom.current().nextInt(min, max + 1);
+ if (randomNum == 0)
+ location = VMConstants.LOCAL;
else
- return false;
+ location = VMConstants.REMOTE;
+ String[] sql = query.split("\\s+");
+ if (sql.length > 3 && sql[0].toLowerCase().equals("create") && sql[1].toLowerCase().equals("table")) {
+ String mainStatement = query.substring(query.indexOf(sql[2]));
+ String tableName = mainStatement.substring(0, mainStatement.indexOf("("));
+ if (DatabaseUtils.getTableLocation(Main.databaseName, tableName) != null) {
+ logger.error("Table already exists! choose a different name!");
+ return new OperationStatus(Boolean.FALSE, Main.databaseName);
+ }
+ String schema = mainStatement.substring(mainStatement.indexOf("(") + 1, mainStatement.indexOf(";") - 1);
+ String columnNames = "";
+ String[] columns = schema.split(",");
+ int i = 0;
+ for (String col : columns) {
+ col = col.trim();
+ columnNames += col.substring(0, col.indexOf(" "));
+ if (i != columns.length - 1)
+ columnNames += "|";
+ i++;
+ }
+ columnNames += "\n";
+ String schemaRow[] = schema.split(",");
+ schema = "ColumnName|Datatype|Constraint" + "\n";
+ for (int j = 0; j < schemaRow.length; j++) {
+ String temp = schemaRow[j].trim();
+ temp = temp.replaceFirst(" ", "|").replaceFirst(" ", "|");
+ schema += temp;
+ if (j != columns.length - 1)
+ schema += "\n";
+ }
+ if (randomNum == 0) {
+ FileOperations.writeToExistingFile(columnNames, tableName + ".psv", DataConstants.DATABASES_FOLDER_LOCATION + Main.databaseName + "/");
+ FileOperations.writeToExistingFile(schema, tableName + "_Schema" + ".psv", DataConstants.DATABASES_FOLDER_LOCATION + Main.databaseName + "/");
+ FileOperations.writeToExistingFile("\n" + tableName + "|" + VMConstants.LOCAL, Main.databaseName + ".psv", DataConstants.DATABASES_FOLDER_LOCATION);
+ RemoteVmUtils.writeToExistingFile("\n" + tableName + "|" + VMConstants.REMOTE, Main.databaseName + ".psv", DataConstants.DATABASES_FOLDER_LOCATION);
+ } else {
+ RemoteVmUtils.writeToExistingFile(columnNames, tableName + ".psv", DataConstants.DATABASES_FOLDER_LOCATION + Main.databaseName + "/");
+ RemoteVmUtils.writeToExistingFile(schema, tableName + "_Schema" + ".psv", DataConstants.DATABASES_FOLDER_LOCATION + Main.databaseName + "/");
+ FileOperations.writeToExistingFile("\n" + tableName + "|" + VMConstants.REMOTE, Main.databaseName + ".psv", DataConstants.DATABASES_FOLDER_LOCATION);
+ RemoteVmUtils.writeToExistingFile("\n" + tableName + "|" + VMConstants.LOCAL, Main.databaseName + ".psv", DataConstants.DATABASES_FOLDER_LOCATION);
+ }
+ return new OperationStatus(Boolean.TRUE, Main.databaseName);
+ } else
+ return new OperationStatus(Boolean.FALSE, Main.databaseName);
}
+ // private boolean isTableExisted(String databaseName, String tableName) throws Exception {
+ // String fileContent=FileOperations.readFileContent(new File(DataConstants.DATABASES_FOLDER_LOCATION + databaseName));
+ // if(fileContent.contains(tableName))
+ // {
+ // return true;
+ // }
+ // else
+ // {
+ // fileContent=RemoteVmUtils.readFileContent(DataConstants.DATABASES_FOLDER_LOCATION + databaseName);
+ // if(fileContent.contains(tableName))
+ // {
+ // return true;
+ // }
+ // }
+ // return false;
+ // }
}
diff --git a/src/main/java/com/dal/distributed/queryImpl/DDL.java b/src/main/java/com/dal/distributed/queryImpl/DDL.java
deleted file mode 100644
index 1e6ec46..0000000
--- a/src/main/java/com/dal/distributed/queryImpl/DDL.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.dal.distributed.queryImpl;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import com.dal.distributed.constant.AuthConstants;
-import com.dal.distributed.main.Main;
-import com.dal.distributed.utils.FileOperations;
-
-public class DDL {
- FileOperations fileOperations=new FileOperations();
- public String insertIntoTable(String sql)
- {
- boolean isTableExist=false;
- String[] query = sql.split("\\s+");
- String tablename=query[2];
- File file[]=fileOperations.readFiles(AuthConstants.DATABASES_FOLDER_LOCATION+Main.databaseName);
- for(File f:file)
- {
- if(f.getName().toLowerCase().contains(tablename))
- {
- isTableExist=true;
- }
- }
- if(!isTableExist)
- return "No table exist";
- else{
-
-
- return AuthConstants.SUCCESS;
-
- }
- }
-
- public List selectQuery()
- {
- List result=new ArrayList<>();
- return result;
- }
-
- public String updateTable(String sql)
- {
- return AuthConstants.SUCCESS;
- }
-
- public String deleteRow(String sql)
- {
- return AuthConstants.SUCCESS;
- }
-
-}
diff --git a/src/main/java/com/dal/distributed/queryImpl/DatabaseCreation.java b/src/main/java/com/dal/distributed/queryImpl/DatabaseCreation.java
deleted file mode 100644
index 4d47bc4..0000000
--- a/src/main/java/com/dal/distributed/queryImpl/DatabaseCreation.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.dal.distributed.queryImpl;
-
-import java.io.File;
-import java.io.IOException;
-
-import com.dal.distributed.constant.AuthConstants;
-import com.dal.distributed.main.Main;
-import com.dal.distributed.utils.FileOperations;
-
-public class DatabaseCreation {
- public boolean createDatabase(String sql,String filepath) throws IOException{
- String[] query = sql.split("\\s+");
- if(query[0].toLowerCase().equals("create")&& query[1].toLowerCase().equals("database")){
- String databaseName = query[2];
- File[] databases=FileOperations.readFiles(filepath);
- if(databases.length==0)
- return false;
- for(File file:databases){
- if(file.getName().toLowerCase().equals(databaseName.toLowerCase())){
- System.out.println("Database already exists! Create new one");
- return false;
- }
- }
- FileOperations.createNewFolder(filepath, databaseName);
- FileOperations.writeToExistingFile(databaseName+"|","databases.psv", AuthConstants.LOGS_FILE_LOCATION);
- return true;
- }
- else
- return false;
-
-}
-
-
-
-public String useDatabase(String sql) throws IOException
-{
- String[] query = sql.split("\\s+");
- if(query.length==2&&query[0].toLowerCase().equals("use")){
- String dbName=query[1];
- File f=new File(AuthConstants.LOGS_FILE_LOCATION+"databases.psv");
- String dbNames=FileOperations.readFileContent(f);
- if(dbNames.toLowerCase().contains(dbName))
- {
- Main.databaseName=dbName;
- return AuthConstants.SUCCESS;
- }
- else
- return "No database exist";
-}
-else return "Wrong query";
-
-}
-}
\ No newline at end of file
diff --git a/src/main/java/com/dal/distributed/queryImpl/DeleteDataFromTable.java b/src/main/java/com/dal/distributed/queryImpl/DeleteDataFromTable.java
index 209efe2..e07cd89 100644
--- a/src/main/java/com/dal/distributed/queryImpl/DeleteDataFromTable.java
+++ b/src/main/java/com/dal/distributed/queryImpl/DeleteDataFromTable.java
@@ -1,45 +1,136 @@
package com.dal.distributed.queryImpl;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
import com.dal.distributed.constant.DataConstants;
+import com.dal.distributed.constant.QueryTypes;
+import com.dal.distributed.constant.RelationalOperators;
+import com.dal.distributed.logger.Logger;
import com.dal.distributed.main.Main;
+import com.dal.distributed.queryImpl.model.OperationStatus;
+import com.dal.distributed.utils.DataUtils;
+import com.dal.distributed.utils.DatabaseUtils;
import com.dal.distributed.utils.FileOperations;
+import com.dal.distributed.utils.RemoteVmUtils;
+
+import java.util.List;
public class DeleteDataFromTable {
- public boolean execute(String query) throws Exception {
- String[] sql = query.split("\\s+");
- String tablename=sql[2];
- String condition=query.substring(query.toLowerCase().indexOf("where")+6,query.indexOf(";"));
- String column_name=condition.substring(0,condition.indexOf("="));
- String value=condition.substring(condition.indexOf("=")+1);
- String databaseName=Main.databaseName;
- int columnIndex=-1;
- String filepath=DataConstants.DATABASES_FOLDER_LOCATION+databaseName+"/"+tablename;
- List> data=new FileOperations().readDataFromPSV(filepath);
- for(int i=0;i> data;
+ String location = null;
+ try {
+ location = DatabaseUtils.getTableLocation(databaseName, tablename);
+ } catch (IllegalArgumentException ex) {
+ logger.error("Database does not exist");
+ }
+ if (location == null) {
+ logger.error("Table does not exist");
+ return new OperationStatus(false);
+ }
+ if (location.equalsIgnoreCase("local")) {
+ data = new FileOperations().readDataFromPSV(filepath);
+ } else {
+ data = new RemoteVmUtils().readDataFromPSV(filepath);
+ }
+ if (data.size() == 1) {
+ System.out.println("No data present in the table");
+ return new OperationStatus(false);
+ }
+ int rowLength = data.size();
+ int columnLength = data.get(0).size();
+ for (int i = 0; i < rowLength; i++) {
+ isRemoved = false;
+ for (int j = 0; j < columnLength; j++) {
+ if (isRemoved)
+ break;
+ if (i == 0)
+ if (data.get(0).get(j).toString().toLowerCase().equals(column_name.toLowerCase())) {
+ columnIndex = j;
break;
}
- if(data.get(i).get(columnIndex).toString().equals(value))
- {
- data.remove(data.get(i));
+ try {
+ switch (relationalOp) {
+ case RelationalOperators.EQUAL:
+ if (data.get(i).get(columnIndex).toString().equals(value)) {
+ data.remove(data.get(i));
+ count++;
+ rowLength -= rowLength;
+ isRemoved = true;
+ }
+ break;
+ case RelationalOperators.GREATER:
+ if (Integer.parseInt(data.get(i).get(columnIndex).toString()) > Integer.parseInt(value)) {
+ data.remove(data.get(i));
+ count++;
+ rowLength -= rowLength;
+ break;
+ }
+ case RelationalOperators.LESS:
+ if (Integer.parseInt(data.get(i).get(columnIndex).toString()) < Integer.parseInt(value)) {
+ data.remove(data.get(i));
+ count++;
+ rowLength -= rowLength;
+ break;
+ }
+ case RelationalOperators.GREATEREQUAL:
+ if (Integer.parseInt(data.get(i).get(columnIndex).toString()) >= Integer.parseInt(value)) {
+ data.remove(data.get(i));
+ count++;
+ rowLength -= rowLength;
+ break;
+ }
+ case RelationalOperators.LESSEQUAL:
+ if (Integer.parseInt(data.get(i).get(columnIndex).toString()) <= Integer.parseInt(value)) {
+ data.remove(data.get(i));
+ count++;
+ rowLength -= rowLength;
+ break;
+ }
+ case RelationalOperators.NOTEQUAL:
+ case RelationalOperators.NOTEQUAL1:
+ case RelationalOperators.NOTEQUAL2:
+ if (Integer.parseInt(data.get(i).get(columnIndex).toString()) != Integer.parseInt(value)) {
+ data.remove(data.get(i));
+ count++;
+ rowLength -= rowLength;
+ break;
+ }
+ operationStatus = new OperationStatus(true);
}
-
+ } catch (NumberFormatException e) {
+ operationStatus = new OperationStatus(false);
}
}
- new FileOperations().writeDataToPSV(data, filepath);
-
- return true;
+ }
+ if (!Main.isTransaction) {
+ if (location.equals("local"))
+ new FileOperations().writeDataToPSV(data, filepath);
+ else
+ new RemoteVmUtils().writeDataToPSV(data, filepath);
+ operationStatus = new OperationStatus(true, data, query, filepath, QueryTypes.UPDATE, tablename, Main.databaseName, count);
+ } else {
+ operationStatus = new OperationStatus(true, data, query, filepath, QueryTypes.UPDATE, tablename, Main.databaseName, count);
+ }
+ return operationStatus;
}
}
diff --git a/src/main/java/com/dal/distributed/queryImpl/InsertIntoTable.java b/src/main/java/com/dal/distributed/queryImpl/InsertIntoTable.java
index 28f316e..366400c 100644
--- a/src/main/java/com/dal/distributed/queryImpl/InsertIntoTable.java
+++ b/src/main/java/com/dal/distributed/queryImpl/InsertIntoTable.java
@@ -1,7 +1,172 @@
package com.dal.distributed.queryImpl;
+import com.dal.distributed.constant.DataConstants;
+import com.dal.distributed.constant.QueryRegex;
+import com.dal.distributed.constant.QueryTypes;
+import com.dal.distributed.logger.Logger;
+import com.dal.distributed.main.Main;
+import com.dal.distributed.queryImpl.model.OperationStatus;
+import com.dal.distributed.utils.DatabaseUtils;
+import com.dal.distributed.utils.FileOperations;
+import com.dal.distributed.utils.RemoteVmUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.stream.Collectors;
+
public class InsertIntoTable {
- public void execute(String query) {
+ Logger logger = Logger.instance();
+ FileOperations fileOperations = new FileOperations();
+
+ public OperationStatus execute(String sql) throws Exception {
+ OperationStatus operationStatus = null;
+ String[] query = sql.split("\\s+");
+
+ // If user enters schema.tableName
+ String[] table = query[2].split("\\.");
+ String tableName = null;
+ String databaseName = null;
+
+ // If user has executed "USE databaseName"
+ if (table.length == 2) {
+ databaseName = table[0];
+ tableName = table[1];
+ } else if (!Main.databaseName.isEmpty()) {
+ databaseName = Main.databaseName;
+ tableName = table[0];
+ } else {
+ logger.error("No database selected.");
+ return new OperationStatus(false);
+ }
+
+ String location = null;
+ try {
+ location = DatabaseUtils.getTableLocation(databaseName, tableName);
+ } catch (IllegalArgumentException ex) {
+ logger.error("Database does not exist");
+ return new OperationStatus(false, databaseName);
+ }
+
+ List> schema = new ArrayList<>();
+ if (null == location) {
+ logger.error("Table '" + databaseName + "." + query[2] + "' doesn't exist");
+ return new OperationStatus(false, databaseName);
+ } else if (location.equalsIgnoreCase("local")) {
+ schema = fileOperations.readDataFromPSV(
+ DataConstants.DATABASES_FOLDER_LOCATION + databaseName + "/" + tableName + "_Schema.psv");
+ } else if (location.equalsIgnoreCase("remote")) {
+ schema = RemoteVmUtils.readDataFromPSV(
+ DataConstants.DATABASES_FOLDER_LOCATION + databaseName + "/" + tableName + "_Schema.psv");
+ }
+
+ String[] values = extractValuesFromQuery(sql);
+
+ if (values.length != schema.size() - 1) {
+ logger.error("Fields count mismatch: Expected " + (schema.size() - 1) + " fields but received "
+ + values.length);
+ return new OperationStatus(false, databaseName);
+ }
+
+ String tablePath = DataConstants.DATABASES_FOLDER_LOCATION + databaseName + "/" + tableName + ".psv";
+ // Primary Key already exists in the database
+ if (checkForPrimaryKeyConstraint(tablePath, schema, values, location)) {
+ return new OperationStatus(false, databaseName);
+ }
+
+ for (int i = 0; i < values.length; i++) {
+ values[i] = values[i].trim();
+ if (schema.get(i + 1).get(1).equals("int")) {
+ String value;
+ // store value = 5 instead of "5"
+ if (values[i].contains("'")) {
+ Matcher matcher = QueryRegex.valueBetweenQuotes.matcher(values[i]);
+ value = matcher.group();
+ } else {
+ value = values[i];
+ }
+ try {
+ Integer.parseInt(value);
+ } catch (NumberFormatException ex) {
+ logger.error("Incorrect integer value: '" + values[i] +
+ "' for column '" + schema.get(i + 1).get(0) + "'");
+ return new OperationStatus(false, databaseName);
+ }
+ }
+ }
+ String finalValue = Arrays.stream(values).collect(Collectors.joining("|"));
+
+ if (!Main.isTransaction) {
+ if (location.equalsIgnoreCase("local")) {
+ fileOperations.writeStringToPSV(finalValue, tablePath);
+ } else {
+ RemoteVmUtils.writeStringToPSV(finalValue, tablePath);
+ }
+ operationStatus = new OperationStatus(true, null, sql, tablePath, QueryTypes.INSERT, tableName,
+ databaseName, 1);
+ } else {
+ List> result = new ArrayList<>();
+ List