Skip to content

Commit

Permalink
step 9 test
Browse files Browse the repository at this point in the history
  • Loading branch information
Sudarshan-21 committed May 15, 2024
1 parent 0992a61 commit 66877a7
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 26 deletions.
3 changes: 2 additions & 1 deletion enrollment.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ student_id,course
1,Mathematics
1,Physics
2,Chemistry
3,Mathematics
3,Mathematics
5,Biology
134 changes: 111 additions & 23 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,106 @@ const fs = require("fs");
const parseQuery = require("./queryParser");
const readCSV = require("./csvReader");

function performInnerJoin(data, joinData, joinCondition, fields, table) {
return data.flatMap((mainRow) => {
return joinData
.filter((joinRow) => {
const mainValue = mainRow[joinCondition.left.split(".")[1]];
const joinValue = joinRow[joinCondition.right.split(".")[1]];
return mainValue === joinValue;
})
.map((joinRow) => {
return fields.reduce((acc, field) => {
const [tableName, fieldName] = field.split(".");
acc[field] =
tableName === table ? mainRow[fieldName] : joinRow[fieldName];
return acc;
}, {});
});
});
}

function performLeftJoin(data, joinData, joinCondition, fields, table) {
return data.flatMap((mainRow) => {
const matchingJoinRows = joinData.filter((joinRow) => {
const mainValue = getValueFromRow(mainRow, joinCondition.left);
const joinValue = getValueFromRow(joinRow, joinCondition.right);
return mainValue === joinValue;
});

if (matchingJoinRows.length === 0) {
return [createResultRow(mainRow, null, fields, table, true)];
}

return matchingJoinRows.map((joinRow) =>
createResultRow(mainRow, joinRow, fields, table, true)
);
});
}

function getValueFromRow(row, compoundFieldName) {
const [tableName, fieldName] = compoundFieldName.split(".");
return row[`${tableName}.${fieldName}`] || row[fieldName];
}

function performRightJoin(data, joinData, joinCondition, fields, table) {
// Cache the structure of a main table row (keys only)
const mainTableRowStructure =
data.length > 0
? Object.keys(data[0]).reduce((acc, key) => {
acc[key] = null; // Set all values to null initially
return acc;
}, {})
: {};

return joinData.map((joinRow) => {
const mainRowMatch = data.find((mainRow) => {
const mainValue = getValueFromRow(mainRow, joinCondition.left);
const joinValue = getValueFromRow(joinRow, joinCondition.right);
return mainValue === joinValue;
});

// Use the cached structure if no match is found
const mainRowToUse = mainRowMatch || mainTableRowStructure;

// Include all necessary fields from the 'student' table
return createResultRow(mainRowToUse, joinRow, fields, table, true);
});
}

function createResultRow(
mainRow,
joinRow,
fields,
table,
includeAllMainFields
) {
const resultRow = {};

if (includeAllMainFields) {
// Include all fields from the main table
Object.keys(mainRow || {}).forEach((key) => {
const prefixedKey = `${table}.${key}`;
resultRow[prefixedKey] = mainRow ? mainRow[key] : null;
});
}

// Now, add or overwrite with the fields specified in the query
fields.forEach((field) => {
const [tableName, fieldName] = field.includes(".")
? field.split(".")
: [table, field];
resultRow[field] =
tableName === table && mainRow
? mainRow[fieldName]
: joinRow
? joinRow[fieldName]
: null;
});

return resultRow;
}

function evaluateCondition(row, clause) {
const { field, operator, value } = clause;
switch (operator) {
Expand Down Expand Up @@ -42,30 +142,18 @@ async function executeSELECTQuery(query) {

// Perform INNER JOIN if specified
if (joinTable && joinCondition) {
const joinFilePath = `${joinTable}.csv`;
if (!fs.existsSync(joinFilePath)) {
throw new Error(`CSV file '${joinFilePath}' not found`);
const joinData = await readCSV(`${joinTable}.csv`);
switch (joinType.toUpperCase()) {
case "INNER":
data = performInnerJoin(data, joinData, joinCondition, fields, table);
break;
case "LEFT":
data = performLeftJoin(data, joinData, joinCondition, fields, table);
break;
case "RIGHT":
data = performRightJoin(data, joinData, joinCondition, fields, table);
break;
}

console.log(`Reading join data from file: ${joinFilePath}`);
const joinData = await readCSV(joinFilePath);

data = data.flatMap((mainRow) => {
return joinData
.filter((joinRow) => {
const mainValue = mainRow[joinCondition.left.split(".")[1]];
const joinValue = joinRow[joinCondition.right.split(".")[1]];
return mainValue === joinValue;
})
.map((joinRow) => {
return fields.reduce((acc, field) => {
const [tableName, fieldName] = field.split(".");
acc[field] =
tableName === table ? mainRow[fieldName] : joinRow[fieldName];
return acc;
}, {});
});
});
}

// Apply WHERE clause filtering
Expand Down
25 changes: 24 additions & 1 deletion src/queryParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,27 @@ function parseWhereClause(whereString) {
});
}

module.exports = parseQuery;
function parseJoinClause(query) {
const joinRegex =
/\s(INNER|LEFT|RIGHT) JOIN\s(.+?)\sON\s([\w.]+)\s*=\s*([\w.]+)/i;
const joinMatch = query.match(joinRegex);

if (joinMatch) {
return {
joinType: joinMatch[1].trim(),
joinTable: joinMatch[2].trim(),
joinCondition: {
left: joinMatch[3].trim(),
right: joinMatch[4].trim(),
},
};
}

return {
joinType: null,
joinTable: null,
joinCondition: null,
};
}

module.exports = { parseQuery, parseJoinClause };
3 changes: 2 additions & 1 deletion student.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
id,name,age
1,John,30
2,Jane,25
3,Bob,22
3,Bob,22
4,Alice,24

0 comments on commit 66877a7

Please sign in to comment.