๋๋ง์ ์ฒดํฌํฌ์ธํธ
์ค๊ณํ๊ธฐ
-
์ค๊ณ - ๊ธฐ๋ณธ ์ธํฐํ์ด์ค โ 2024-08-05
-
์ค๊ณ - create โ 2024-08-05
-
์ค๊ณ - insert โ 2024-08-05
-
์ค๊ณ - delete โ 2024-08-05
-
์ค๊ณ - update โ 2024-08-05
-
์ค๊ณ - select โ 2024-08-05
-
์ค๊ณ - drop โ 2024-08-05
๊ตฌํํ๊ธฐ
-
๊ธฐ๋ณธ ์ธํฐํ์ด์ค โ 2024-08-06
-
create โ 2024-08-06
-
insert โ 2024-08-06
-
delete โ 2024-08-06
-
update โ 2024-08-06
-
select โ 2024-08-06
-
drop โ 2024-08-06
๋ฌธ์ ํด๊ฒฐ ๊ณผ์
์ค๊ณํ๊ธฐ
ํด๋น ํ์ต๋ชฉํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ด๋ฆฌ ์์คํ ํ์ต์ ์ํ SQL ๋ฌธ๋ฒ๊ณผ ์ ์ฌํ๊ฒ ํ์ผ ๊ธฐ๋ฐ์ผ๋ก ํ ์ด๋ธ์ ๊ด๋ฆฌํ๊ณ Record๋ฅผ ์์ฑ, ์ ๋ฐ์ดํธ, ์ญ์ ํ๋ ํ๋ก๊ทธ๋จ์ ๋ง๋๋ ๊ฒ์ด ๋ชฉํ์ด๋ค.
์ด๋ฌํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ด๋ฆฌํ๊ธฐ ์ํด์๋ ์์ฒญ์ ๋ณด๋ด์ผ ํ๋๋ฐ, ์ด๋ฌํ ์์ฒญ์ http ์์ฒญ๊ณผ ์๋ต ํ์์ผ๋ก ๊ตฌํํจ์ผ๋ก์จ http ํต์ ์ ๋ํ ์ดํด๋ ๋ํ ํจ์์ํค๊ธฐ ์ํ ๋ฌธ์ ๋ผ๊ณ ์๊ฐํ๋ค.
๋งจ ์ฒ์ ์ค๊ณ์์ ๊ตฌํํ ๋ ๊ณ ๋ฏผํ๋ ๋ถ๋ถ์ ์ฝ์ด๋ค์ด๋ CSV ํ์ผ์ ๋ํด ์ด๋ป๊ฒ ๊ด๋ฆฌํ ๊ฒ์ด๋๋ฅผ ๊ณ ๋ฏผํ๋ค.
singer,year,song
-----------
honux,2016,Gameover
jk,2020,I like steak
crong,2023,Milk song
ivy,2021,Butter
๋ฌธ์ ์ ์์์์๋ CSV ํ์ผ์ ์ฃผ์๋๋ฐ, ์ด๋ฌํ ํ์ผ์ ๋ํด์ ๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ์ญ์ ๋ฑ ๋ค์ํ ๋ช ๋ น์ด๋ค์ ๋ํด์ ์ฒ๋ฆฌํ ์ ์์ด์ผ ํ๋ค. ์ด๋ฅผ ์ํด์๋ CSV ํ์ผ์ ์ฝ์ด๋ค์ธ ๋ค์ ์ ์ ํ ๋ฐ์ดํฐ ํ์ ์ผ๋ก ๋ณํํด์ค ๋ค์์ ๊ด๋ฆฌํ๋ ๊ฒ์ด ๋ณด๋ค ํฉ๋ฆฌ์ ์ด๋ผ๊ณ ์๊ฐํ๋ค.
๋์ ๊ฒฝ์ฐ๋ Tableํด๋์ค์ ๊ฐ Column(Attribute)๊ณผ ๋ ์ฝ๋๋ฅผ ๋ฐฐ์ด๋ก ๋ฐ๋ก ์ ์ฅํด๋๋ ๊ฒ์ ์๊ฐํ๋ค.
์ฌ๊ธฐ์ ๋ ์ฝ๋๋ฅผ ๊ฐ์ฒด๋ก ๋ฐ๋ก ๋ง๋ค์ง ์์ ์ด์ ๋ ๋์ค์ ๊ณ์ํด์ ์ ๋ณด๋ฅผ ๊ฐฑ์ ํ๋ ๊ณผ์ ์์ insertํ ๋ ์์๋ฅผ ๊ฐ์ง๋ ํ๋กํผํฐ๋ฅผ ํ๋ ๋ ๋ ์ผ๋ก์จ ๊ฐ attribute๊ฐ ์ด๋ ํ ์ธ๋ฑ์ค๋ฅผ ๊ฐ์ง๋์ง ๋ํ๋ด๋ ค๊ณ ํ๋ค.
classDiagram class Table{ +attr_count +attributes: array +records: record[] #parsing() #saveToFile() }
๊ธฐ๋ณธ ์ธํฐํ์ด์ค
๊ธฐ๋ณธ ์ธํฐํ์ด์ค๋ ์ ๋ฒ mit ๋ฏธ์ ์์ ์ฌ์ฉํ๋ commander ํจํค์ง๋ฅผ ์ฌ์ฉํ์ฌ ์ฒ๋ฆฌํ๋ ค๊ณ ํ๋ค. ๋ด ์์กด์ฑ์ ์ค์นํ๊ณ ์คํ์ํค๋ฉด ์ด์ ํด๋นํ๋ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํ ์ ์๋ ์ธํฐํ์ด์ค๋ฅผ ์ฃผ๊ณ , ๊ฐ ๋ช ๋ น์ด๋ฅผ ๋ฐ๋ก ํ์ฑํ์ฌ ์ฒ๋ฆฌํ ๋ค์์ ํด๋น ์ฟผ๋ฆฌ์ ๋ช ๋ น์ ๋ฐ๋ผ ๋ค๋ฅธ ํจ์ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๋ ค๊ณ ํ๋ค.
Create
Create ์์ฒญ์ ๊ฒฝ์ฐ ํ ์ด๋ธ์ ์์ฑํ๋ ์์ฒญ์ผ๋ก ๋ด๊ฐ ์ค์ ํ๋ ค๋ ํ ์ด๋ธ์ Attribute(Column)์ ์ค์ ํ๋ค.
CREATE table_name BTTP
Column: column1=datatype
Column: column2=datatype
Column: column3=datatype
create ์์ฒญ์ ๊ฒฝ์ฐ ์๋กญ๊ฒ csv ํ์ผ์ ๋ง๋ค์ด์ผ ํ๋ฉฐ,
-
ํ์ ๊ฒ์ฌ
-
datatype ์ถ์ถํด์ ๊ฐ์ฒด ๋ง๋ค๊ธฐ
-
๊ฐ์ฒด ํ์ผ๋ก ์ ์ฅ
์ ๊ณผ์ ์ ๊ฑฐ์ณ attribute๋ค๋ง ์๋ CSV ํ์ผ์ ์ ์ฅํ๋ค.
์ฌ๊ธฐ์ ์ ์ฝ์ฌํญ์ผ๋ก 9๊ฐ๊น์ง๋ง ์ง์ํ๋๋ก ํ๋ ์กฐ๊ฑด๊ณผ
์ฌ๊ธฐ์ ์ถ๊ฐ์ ์ผ๋ก datatype์ ๊ฒ์ฌํด์ Numeric, String๋ง์ ๋ฃ์ ์ ์๊ฒ ํด์ผ ํ๊ณ , attribute์ ๋ํด์๋ ๋์ค์ ํด๋นํ๋ ๋ฐ์ดํฐํ์ ์ ๊ฒ์ฌํด์ ๋ฐ์ดํฐ๋ฅผ ์์ฑํด์ผ ํ๋ฏ๋ก ๊ฐ attribute ๋ํ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด key:value ํํ๋ก ๋ฐ์ดํฐํ์ ์ ๋ฃ์ด ํ ์ ์๊ฒ ํ๋ ค๊ณ ํ๋ค.
Insert
Insert ์์ฒญ์ ํ ์ด๋ธ์ ๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ ๋ฉ์๋์ด๋ค.
INSERT table_name BTTP
Column: column1
Column: column2
Value: value1
Value: value2
๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ฉด์ column๊ฐ์๋ฅผ ๊ฒ์ฌํ์ฌ ๊ธฐ์กด์ column ๊ฐ์์ ๊ฐ์ง ์์ผ๋ฉด ์์ธ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
๊ฐ์๊ฐ ๊ฐ๋ค๋ฉด column์ ์์๋๋ก value๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ๋ ๊ฒ ๊ฐ๋ค.
Delete
delete๋ ํ ์ด๋ธ์ ๋ ์ฝ๋๋ฅผ ์ญ์ ํ๋ ๊ฒ์ผ๋ก, condition์ ๋ง๋ ๊ฒ๋ค์ ๋ชจ๋ ์ญ์ ํ๋ค. ์ด ๋ condition์ ํ๋๋ง ํฌํจํ๋ฉด ๋๋ฏ๋ก attribute์ ์กฐ๊ฑด, ๋ ผ๋ฆฌ์ฐ์ฐ์๋ฅผ ์ถ์ถํด๋ด์ด ๊ฒ์ฌํ๋ค.
Update
๋ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ๋ ๋ฉ์๋๋ก ์กฐ๊ฑด์ ๋ง๋ ๋ ์ฝ๋์ ํน์ ์ปฌ๋ผ ๊ฐ์ ๋ณ๊ฒฝํ๋ฉด ๋๋ฏ๋ก ์ด ๋ํ attribute์ ์กฐ๊ฑด, ๋ ผ๋ฆฌ์ฐ์ฐ์๋ฅผ ์ถ์ถํด๋ด์ด ์ฒ๋ฆฌํ๋ฉด ๋๋ค.
Select
ํ ์ด๋ธ์ ๋ ์ฝ๋๋ฅผ ๊ฒ์ํ๋ ํ์์ผ๋ก, ์กฐ๊ฑด์ ๋ง๋ ์ปฌ๋ผ๋ง ์ถ๋ ฅํ๋ฉด ๋๋ค.
Drop
ํ ์ด๋ธ ์ด๋ฆ๊ณผ ๋์ผํ CSVํ์ผ์ ํต์ฑ๋ก ์ญ์ ํ๋ฉด ๋๋ค.
๊ตฌํํ๊ธฐ
์ธํฐํ์ด์ค
#!/usr/bin/env node
const { program } = require("commander");
const { commandInterface } = require("./interface");
program.version("0.0.1", "-v, --version").name("commander");
program.command("run").action(() => {
commandInterface();
});
program.parse(process.argv);
์ธํฐํ์ด์ค์ ๊ฒฝ์ฐ ์์ ์ ์์ mhcsv run์ ํฐ๋ฏธ๋์ ์ ๋ ฅํ๋ฉด ๋ช ๋ น์ด ์ฐฝ์ด ๋์จ๋ค. ์ดํ์ ๋ช ๋ น์ด๋ค์ ๊ณ์ํด์ ์คํํ ์ ์๋ค.
์ฃผ์ด์ง๋ ์ ๋ ฅ์ commandInterface๋ฅผ ํตํด ์คํ๋๊ณ ์ฒ๋ฆฌํ๋ค.
const readline = require("readline");
const { parsingCommand } = require("./parsing");
const { handleCommand } = require("./handlecommand");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
const commandInterface = (command) => {
console.log("์คํํ ์์ฒญ ํ์ผ์ ์
๋ ฅํ์ธ์\n");
rl.on("line", (line) => {
if (!line || line === "q") rl.close();
try {
const { command, file } = parsingCommand(line);
console.log(">>>>>>>>>>>>\n");
handleCommand(file);
} catch (error) {
console.log("<<<<<<<<<<<");
console.log(error.message);
}
});
};
module.exports = { commandInterface };
๋๊ฐ์ ๊ฒฝ์ฐ๋ ๋ช ๋ น์ด ์ฐฝ์ ๊ณ์ ์ผ๋๊ณ ํด๋น ๋ช ๋ น์ด๋ฅผ ๊ทธ๋๋ง๋ค ํ์ฑํ์ฌ ์๋ง์ ์ปค๋งจ๋์ ๋ํ ์คํ์ handleCommand๊ฐ ๋ด๋นํ๋ค.
const { readFileSync } = require("fs");
const { create } = require("./create");
const { insert } = require("./insert");
const { deleteRecord } = require("./delete");
const { update } = require("./update");
const { drop } = require("./drop");
function handleCommand(fileName) {
const command = readFileSync(`./${fileName}`)
.toString()
.split("\n")[0]
.split(" ")[0];
switch (command) {
case "CREATE":
create(fileName);
break;
case "INSERT":
insert(fileName);
break;
case "DELETE":
deleteRecord(fileName);
break;
case "UPDATE":
update(fileName);
break;
case "SELECT":
break;
case "DROP":
drop(fileName);
break;
default:
throw new Error("400 Bad Request");
}
}
module.exports = { handleCommand };
์ด์ฒ๋ผ switch/case๋ฌธ์ ํตํด ๊ฐ ๋ช ๋ น์ด์ ๋ํด์ ํจ์๋ฅผ ์คํํ๋๋ก ๊ตฌํํ๋ค.
ํ ์ด๋ธ ํด๋์ค
const { readFileSync, existsSync, writeFileSync } = require("fs");
const { getTableName } = require("./create");
class Table {
constructor(tableName, types, attributes, records) {
this.tableName = tableName;
this.types = types;
this.attributes = attributes;
this.attributesLen = this.attributes.length;
this.records = records;
this.currIdx = this.records.length + 1;
this.index = this.#getIndex();
}
static getFile(fileName) {
console.log(readFileSync(`./${fileName}`).toString());
const fileData = readFileSync(`./${fileName}`).toString().split("\n");
const tableName = getTableName(fileData[0]);
if (!existsSync(`./${tableName}.csv`) || !existsSync(`./${tableName}.json`))
throw new Error("404 CSV file Not Found");
const data = readFileSync(`./${tableName}.csv`).toString().split("\n");
const metaData = JSON.parse(readFileSync(`./${tableName}.json`).toString());
let attributes = [];
if (data.length > 1) {
attributes = data.slice(1, data.length - 1).map((attr) => {
let attrArr = attr.split(",");
attrArr = attrArr.map((attr) => {
if (!attr.includes('"')) return parseInt(attr);
return attr;
});
return attrArr;
});
}
console.log("<<<<<<<<<<");
return new Table(tableName, metaData.types, data[0].split(","), attributes);
}
#getIndex() {
let index = {};
this.attributes.forEach((attr, idx) => {
index[attr] = idx;
});
return index;
}
saveToFile() {
let fileData = this.attributes.join(",") + "\n";
this.records.forEach((record) => {
fileData += record.join(",") + "\n";
});
writeFileSync(`./${this.tableName}.csv`, fileData);
console.log("200 OK");
console.log("Content-Type: Text/JSON");
console.log(`Content-Length: ${fileData.length}`);
}
insert(values) {
if (values.length !== this.attributesLen - 1)
throw new Error("400 values have different length");
const types = Object.values(this.types);
const newRecord = { id: this.currIdx };
values.forEach((val, index) => {
if (types[index + 1] !== typeof val) {
throw new Error("400 type not matched");
}
newRecord[this.attributes[index + 1]] = val;
});
this.records.push([this.currIdx, ...values]);
this.currIdx++;
console.log(newRecord);
this.saveToFile();
}
delete(targetIndex, targetVal) {
this.records = this.records.filter((record) => {
record[targetIndex] !== targetVal;
});
this.saveToFile();
}
update(col, val, con_col, con_val) {
if (!this.index.hasOwnProperty(col))
throw new Error("404 column not Found");
if (!this.index.hasOwnProperty(con_col))
throw new Error("404 condition column not Found");
const targetCol = this.index[con_col];
const updateCol = this.index[col];
this.records.forEach((record, idx) => {
if (record[targetCol] == con_val) {
record[updateCol] = val;
}
});
this.saveToFile();
}
}
module.exports = { Table };
๊ธฐ์กด์ ์ค๊ณํ๋ ํ๋กํผํฐ๋ค๊ณผ ๋ฉ์๋๊ฐ์๋ ์ฐจ์ด๊ฐ ๋ค์ ์๋ค.
\๊ณ์ํด์ ์ฐ์ด๋ ํ์ผ์ ์ฝ์ด ์ฒ๋ฆฌํ๋ ๊ธฐ๋ฅ์ ์ ์ ๋ฉ์๋๋ก ๊ตฌํํ์ฌ ์๋ก์ด Table ๊ฐ์ฒด๋ฅผ ๋ฐํํ๊ฒ ํจ์ผ๋ก์จ ํด๋น ํ ์ด๋ธ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ํด๋์๋ค. ๊ฐ ๋ช ๋ น์ด์ ๋ฉ์๋๋ ๊ทธ์ ๋ฐ๋ฅธ ํจ์๊ฐ ์์ง๋ง, ์ต์ข ์ ์ผ๋ก๋ ๋๋ถ๋ถ ์ด ๋ฉ์๋๋ค์ ํตํด์ ์ ๋ณด๊ฐ ๊ฐฑ์ ๋๋ค.
ํ๋กํผํฐ๊ฐ์ ๊ฒฝ์ฐ๋ ์ดํธ๋ฆฌ๋ทฐํธ์ ๊ทธ ๊ธธ์ด, ๋ ์ฝ๋์ ํ์ฌ์ ๋ id๊ฐ, index๋ ๊ฐ ์ดํธ๋ฆฌ๋ทฐํธ๋ง๋ค ๊ฐ์ง๋ ์ธ๋ฑ์ค๋ฅผ ๊ฐ์ฒด ํํ๋ก ๊ธฐ๋กํด๋์๋ค.
ํ์ ๊ฐ์ ๊ฒฝ์ฐ๋ ๋ฐ๋ก ๋ง๋ json ํ์ผ์ ๊ฐ์ง๊ณ ํด๋น ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํ์ ํ๋กํผํฐ์ ๋ฃ์ด์ฃผ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋ค.
Create
const { writeFileSync, existsSync, readFileSync, mkdir } = require("fs");
function create(fileName) {
let attributes = [`id`];
let metaData = { fileName: fileName, types: { id: "number" } };
let tableName;
const data = readFileSync(`./${fileName}`).toString();
data.split("\n").forEach((attr, idx) => {
console.log(attr);
if (idx === 0) tableName = getTableName(attr);
else {
if (!attr) return;
const { attribute, type } = getColumn(attr);
attributes.push(`${attribute}`);
if (type === "Numeric") metaData.types[attribute] = "number";
else metaData.types[attribute] = "string";
}
});
if (existsSync(`./${tableName}.csv`))
throw new Error("409 File Already Exists");
writeFileSync(`./${tableName}.csv`, attributes.join(",") + "\n");
writeFileSync(`./${tableName}.json`, JSON.stringify(metaData));
console.log("\n<<<<<<<<<<<");
console.log("201 Created");
}
const getTableName = (line) => {
const [_, tableName, bttp] = line.split(" ");
if (bttp !== "BTTP") throw new Error("400 Invalid Bttp request");
return tableName;
};
const getColumn = (line) => {
const regex = /^Column:\s(\w+)\=(String|Numeric)/;
if (!regex.test(line)) throw new Error("400 Invalid Column Syntax");
const attribute = line.match(regex)[1];
const type = line.match(regex)[2];
return { attribute, type };
};
module.exports = { create, getTableName };
create๋ ์ฒ์ bttp ํ์ผ์ ๋ํด์ ์ฒ๋ฆฌ๋ฅผ ํด์ค์ผ ํ๋ฏ๋ก ๋ค์ ๊ธด ๊ฒฝํฅ์ด ์๋ค.
์ฃผ์ ๋ก์ง์
-
ํ์ผ์ ์ฝ์ด ์ค๋ง๋ค ์ฒ๋ฆฌ + ์ ํจ์ฑ ๊ฒ์ฆ
-
numericํ์ ์ด ์๋ฐ์คํฌ๋ฆฝํธ์์ typeof๋ฅผ ์ฌ์ฉํ ๋ ์ ์ฉํ์ง ์์ผ๋ฏ๋ก number๋ก ์นํ
-
์๋ก์ด JSON ํ์ผ์ ํ์ ์ ๋ณด๋ฅผ ๋ณด๊ด ๋ฐ ์ ์ฅ
์ ๋ก์ง์ ๊ฐ์ง๋ค.
์๋๊ฒฐ๊ณผ

์ผํธ~

insert
const { readFileSync, existsSync } = require("fs");
const { getTableName } = require("./create");
const { Table } = require("./table");
function insert(fileName) {
const insertData = readFileSync(`./${fileName}`)
.toString()
.split("\n")
.slice(1);
const table = Table.getFile(fileName);
const { attrs, values } = getAttrAndVal(insertData);
table.insert(values);
}
const getAttrAndVal = (insertData) => {
const attrs = [];
const values = [];
insertData.forEach((data) => {
let [colOrVal, val] = data.split(" ");
if (colOrVal === "Column:") {
if (!val.includes('"')) val = parseInt(val);
attrs.push(val);
} else if (colOrVal === "Value:") {
if (!val.includes('"')) val = parseInt(val);
values.push(val);
} else {
throw new Error("400 Bad Request");
}
});
if (attrs.length !== values.length)
throw new Error("400 Column not matched to Value");
return { attrs, values };
};
module.exports = { insert };
insert๋ ์๊ฐ๋ณด๋ค ๋ง์ด ๊น๋ค๋ก์ ๋ค. ์ฒ์์๋ ๋ค์ด์ค๋ ๋ชจ๋ ๊ฐ๋ค์ด ๋ฌด์์๋ก ์ฃผ์ด์ ธ์ ํด๋น ์ธ๋ฑ์ค๊ฐ์ ๊ณ์ ๋์กฐํ์ฌ ์๋ง์ ํํ๋ก ๋ ์ฝ๋๋ฅผ ๋ง๋ค์ด ๋ฃ์ด์ผ ํ๋ ๊ฒ์ด ์๋๊น? ์๊ฐํ๋๋ฐ ์ฐพ์๋ดค๋๋ sql ์ฟผ๋ฆฌ๋ฌธ์์๋ ๋ฐ๋ก ์์๋ฅผ ์ง์ ํด์ผ ํ๋ค.
INSERT INTO Temp_Table(field1, field2, field4, field3, field5, field6, field7, field8, field9, field10)
VALUES('data4','data4-2','data4-4','data4-3','data4-5','data4-6','data4-7','data4-8','data4-9','data4-10');
๋ฐ๋ผ์ ๋๋ ๊ทธ๋ฅ ์ดํธ๋ฆฌ๋ทฐํธ ์์๋๋ก ๋ ์ฝ๋๊ฐ ๋ค์ด์ฌ ๊ฒ์ด๊ณ , ๋๋ ๊ทธ๋ฅ ํ์ ์ฒดํฌ๋ง ํ๋ฉด ๋๊ฒ ๋ค ์๊ฐํ๊ณ ๊ตฌํํ๋ค.
์คํ๊ฒฐ๊ณผ


update
const { readFileSync } = require("fs");
const { Table } = require("./table");
function update(fileName) {
const table = Table.getFile(fileName);
const updateData = readFileSync(`./${fileName}`)
.toString()
.split("\n")
.slice(1);
const [col, colData] = updateData[0].split(" ");
const [val, valData] = updateData[1].split(" ");
let [con, conData] = updateData[2].split(" ");
if (col !== "Column:" || val !== "Value:" || con !== "Condition:")
throw new Error("400 Bad Request(command)");
const [conData_col, conData_val] = conData.split("=");
table.update(colData, valData, conData_col, conData_val);
}
module.exports = { update };
update๋ ์กฐ๊ฑด์ ํด๋นํ๋ ๋ ์ฝ๋๋ฅผ ์ฐพ์์ ์ค์ ํ column๊ฐ์ ์ธ๋ฑ์ค์ ์ง์ ํ value๊ฐ์ ๋ฃ์ด์ฃผ๋๋ก ํ๋ค.
์กฐ๊ฑด์ด ๊น๋ค๋กญ์ง๋ ์์ง๋ง ๊ฐ์ข ํ๋ผ๋ฏธํฐ๋ค์ ํ์ฑ์ด ๋ง๋ค๋ณด๋ ๋ณต์กํด์ง ๊ฒฝํฅ์ด ์๋ค.
์คํ๊ฒฐ๊ณผ


Delete
const { readFileSync } = require("fs");
const { Table } = require("./table");
function deleteRecord(filename) {
const file = Table.getFile(filename);
if (!file.records.length) throw new Error("404 record not exist");
const [text, condition] = readFileSync(`./${filename}`)
.toString()
.split("\n")[1]
.split(" ");
if (text !== "Condition:") throw new Error("400 Bad Request");
const [col, con] = condition.split("=");
if (!col || !con) throw new Error("400 Bad Request(Condition)");
console.log(col, con);
const targetIndex = file.index[col];
file.delete(targetIndex, con);
}
module.exports = { deleteRecord };
...
//ํด๋์ค ๋ฉ์๋
delete(targetIndex, targetVal) {
this.records = this.records.filter((record) => {
record[targetIndex] !== targetVal;
});
this.saveToFile();
}
Delete์ ๊ฒฝ์ฐ์๋ ์กฐ๊ฑด์ ๊ฒ์ํ๋ ๋ฐฉ์์ด update์ ๋น์ทํ๊ฒ ์๋ํ๊ธฐ ๋๋ฌธ์ ์ผ๋ถ๋ถ์ ์ฌํ์ฉํ๋ค.
ํน์ดํ ์ (?)์ผ๋ก๋ ๊ธฐ์กด์ ๋ ์ฝ๋ ๋ฐฐ์ด๋ค์ ๊ณ ์ฐจํจ์ filter๋ฅผ ํตํด ๊ฑธ๋ฌ์ฃผ์ด ์ฝ๋๊ฐ ๋ณด๋ค ๊นจ๋ํด์ก๋ค.
์คํ ๊ฒฐ๊ณผ


SELECT
ํด์ปคํค๋์ ์ค๋นํ๋๋ผ ์๊ฐ๋ถ์กฑ์ด์๋ก ๋ด์ผ ์๊ฐ์ด ๋๋ค๋ฉด ๊ตฌํํ ๋ฏ ์ถ๋ค..
๊ฐ๋ ๋น๋ํ๋ฉด์ ๊ธฐ๋ค๋ฆฌ๋ฉด์ ์กฐ๊ธ์ฉ ํ๋ค.
์๊ณ ์ถ๋ค..
const { readFileSync } = require("fs");
const { Table } = require("./table");
function select(fileName) {
const table = Table.getFile(fileName);
const [con, condition] = readFileSync(`./${fileName}`)
.toString()
.split("\n")[1]
.split(" ");
if (con !== "Condition:") throw new Error("400 Bad Request(condition)");
console.log(condition);
const regex = /(\w+)([=><])([\w"]+)/;
const matched = condition.match(regex);
const col = matched[1];
const logic = matched[2];
const val = matched[3];
table.select_equal(col, val);
}
module.exports = { select };
...
//ํ
์ด๋ธ ํด๋์ค ๋ฉ์๋
select_equal(col, val) {
const idx = this.index[col];
const result = [];
this.records.forEach((record) => {
if (record[idx] === val) {
result.push(record);
}
});
this.recordToObject(result);
}
recordToObject(arr) {
const result = [];
arr.forEach((record) => {
let converted = {};
record.forEach((attr, idx) => {
converted[this.attributes[idx]] = attr;
});
result.push(converted);
});
console.log(result);
}
Select์ ๊ฒฝ์ฐ ํ์ฌ๋ equal = ๋ง ๋ฐ๋ก ์ฒ๋ฆฌ๋ฅผ ํ๋ ๋ก์ง์ ๋ง๋ค์ด๋จ๋ค.
์๊ฐํด๋ณด๋ ์ผ์น์ ๊ฐ์ ๊ฒฝ์ฐ๋ ์ด์ฐจํผ index๊ฐ์ ํตํด ๊ฐ ์ดํธ๋ฆฌ๋ทฐํธ์ ๋ํ ๊ฐ์ ์ ๋ฝ์๋ผ ์ ์์ผ๋ฏ๋ก ๋งจ ์ฒ์์ ์ ๊ทํํ์์ ํตํด ๊ทธ๋ฃน์บก์ฒ๋ฅผ ํด์ ํ์ํ ์กฐ๊ฑด(์ดํธ๋ฆฌ๋ทฐํธ, ๊ฐ, ๋ ผ๋ฆฌ์ฐ์ฐ์)๋ฅผ ๋ฝ์๋ด๊ณ ๊ฐ๊ฐ ๋ ผ๋ฆฌ์ฐ์ฐ์์ ๋ฐ๋ผ ๋ก์ง์ switch/case๋ฌธ์ ํตํด ์ฒ๋ฆฌํ ์์ ์ด๋ค.
ํ์ฌ ๋ฑํธ๋ง ํด๋จ๋๋ฐ, ๋ฑํธ์ ๊ฒฝ์ฐ์๋ ๋ ์ฝ๋๋ฅผ ์ ๋ถ ๋๋ฉด์ ํด๋น ๊ฐ๊ณผ ๊ฐ์ ๋ ์ฝ๋๋ค๋ง ์ฐพ์๋ด์ ๋ฝ์๋ด๋ฉด ๋๋ค.
์คํ๊ฒฐ๊ณผ


DROP
const { existsSync, readFileSync, unlinkSync } = require("fs");
const { Table } = require("./table");
function drop(fileName) {
if (!existsSync(`./${fileName}`)) throw new Error("404 file not found");
const table = Table.getFile(fileName);
const length = readFileSync(`./${fileName}`).toString().length;
if (!existsSync(`./${fileName}`)) throw new Error(`404 file not found(csv)`);
unlinkSync(`./${table.tableName}.csv`);
unlinkSync(`./${table.tableName}.json`);
console.log("<<<<<<<<<<<");
console.log("200 OK");
console.log(`Row-Count: ${length}`);
}
module.exports = { drop };
DROP์ unlinksync๋ฅผ ์ฌ์ฉํด์ฃผ๊ธฐ๋ง ํ๋ฉด ๋์ผ๋ฏ๋ก ์ผ๋จ์ ์ฒ์์ ํ ์ด๋ธ ๊ฐ์ฒด๋ฅผ ๋ฐ์์ค๋ ์ ์ ๋ฉ์๋๋ฅผ ํตํด์ ํ ์ด๋ธ ๊ฐ์ฒด๋ฅผ ๋ฐ์์จ ๋ค, ํด๋น ํ์ผ ์ด๋ฆ์ ํ๋กํผํฐ๋ฅผ ๊ฐ์ ธ์ ์ด๋ฅผ ์ง์์ฃผ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๋ค.
์คํ๊ฒฐ๊ณผ



ํ์ต
SQL
https://medium.com/@queenskisivuli/how-sql-writes-data-insert-create-and-delete-3b5536d9370b
๋ฐ์ดํฐ๋ฒ ์ด์ค
ํธ๋์ญ์
๊ฐ์ ํ๊ธฐ
- ํจ์๋ถ๋ฆฌ ์ด๋ฒ ๋ฆฌํฉํ ๋ง์์๋ ์ฌ๋ฌ ๋ฉ์๋์ ์ฒ๋ฆฌ๋ฅผ ๋ด๋นํ๋ switch๋ฌธ ์์ ํจ์๋ค์ ๋๋ถ๋ถ ๊ธธ์ด๋ฅผ ์ต๋ํ ์ค์ด๋ ๊ฒ์ด ๋ชฉํ์๋ค. ํผ์ด์ ์ด๋ฌํ ๋ถ๋ถ์ ํ๋์ฉ ๋ณด๋ฉด์ ์ข๋ ์ง์คํ์ฌ ์ฝ๋๋ฅผ ๊ฐ๋ตํ๊ฒ ์ค์ด๋ ๋ฐฉ๋ฒ์ ๋ํด์ ๋ง์ด ๊ณ ์ํ๋ค.
function create(fileName) {
const data = readFileSync(`./${fileName}`).toString();
const { attributes, metaData, tableName } = parsingCreate(data, fileName);
if (existsSync(`./${tableName}.csv`))
throw new Error("409 File Already Exists");
writeFileSync(`./${tableName}.csv`, attributes.join(",") + "\n");
writeFileSync(`./${tableName}.json`, JSON.stringify(metaData));
console.log("\n<<<<<<<<<<<");
console.log(STATUS_CODE[201]);
}
...
const parsingCreate = (data) => {
let attributes = [`id`];
let metaData = { fileName: "", types: { id: "number" } };
let tableName;
data.split("\n").forEach((attr, idx) => {
console.log(attr);
if (idx === 0) {
tableName = Table.getTableName(attr);
metaData.fileName = tableName;
} else {
if (!attr) return;
const { attribute, type } = getColumn(attr);
attributes.push(attribute);
if (type === "Numeric") metaData.types[attribute] = "number";
else metaData.types[attribute] = "string";
}
});
return { tableName, attributes, metaData };
};๋ํ์ ์ธ create ๋ฉ์๋์ ๊ฒฝ์ฐ, ์ด์ ๊น์ง๋ parsingCreate์ด๋ผ๋ ํจ์๋ฅผ ๋ฐ๋ก ๋์ง ์๊ณ ์ด๋ฌํ ๋ฉํ๋ฐ์ดํฐ, ์ดํธ๋ฆฌ๋ทฐํธ, ํ ์ด๋ธ ์ด๋ฆ ๋ฑ์ ์ถ์ถํด ๋ด๋๋ฐ ํด๋น ํจ์ ์์์ ๋ชจ๋ ์ฒ๋ฆฌํ๋ค๋ณด๋ ํจ์์ ๊ฐ๋ ์ฑ ์์ฒด๊ฐ ๋งค์ฐ ๋จ์ด์ก๋ค. ๊ทธ๋ฌ๋ค๋ณด๋ ์ด๋ฌํ ๋ถ๋ถ์ ๊ฐ์ ํด์ผ ํ ํ์์ฑ์ ์์ฐ์ค๋ฝ๊ฒ ๊ตฌํํ๋ ๊ณผ์ ์์ ๋๋ผ๊ฒ ๋์๊ณ , ์ด๋ฅผ ๊ฐ์ ํ๊ธฐ์์ ๊ณ ์ณ์ผ๊ฒ ๋ค๊ณ ์๊ฐํ๋ค. ์ฌ์ค ์กฐ๊ธ ๋ ์ข์ ๋ฐฉ์์ ์ดํธ๋ฆฌ๋ทฐํธ์ ๋ฉํ๋ฐ์ดํฐ, ํ ์ด๋ธ ์ด๋ฆ์ ๋ค ํจ์๋ก ๋ถ๋ฆฌํ๋ค๋ฉด ๋ณด๋ค ํด๋น ํจ์์ ๊ธธ์ด๊ฐ ์งง์์ง ์๋ ์๊ฒ ์ง๋ง, ์ฌ์คํ ํ๋์ ํ์ผ์ ๋ํด ์ฌ๋ฌ๋ฒ ๋ฐ๋ณต๋ฌธ์ ๋๋ฉฐ ์ฒ๋ฆฌํ๋ ๊ผด์ด ๋๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ๋ฉด์์ ์ํด๋ผ๊ณ ์๊ฐํ์ฌ ํ๋์ ํจ์์ ์ฒ๋ฆฌํ๋ ๊ฒ์ผ๋ก ์๊ฐํ๋ค.
- ์ํ ์ฝ๋ ์์ํ
const STATUS_CODE = {
200: "200 OK",
201: "201 CREATED",
400: "400 BAD REQUEST",
404: "404 FILE NOT FOUND",
500: "500 INVALID BTTP REQUEST",
};
module.exports = { STATUS_CODE };
์ํ ์ฝ๋ ์์ํ์ ๊ฒฝ์ฐ ๋ค์ํ ์ํ์ฝ๋๊ฐ ์์ง๋ง ์ฃผ๋ก ์๋ต ์ฝ๋์ ๋ง๋ ๋ฉ์ธ์ง๊ฐ ์๋๋ฐ, ์ด๋ฅผ ๋งค์นํ๊ธฐ ์ํด ์ฌ๋ฌ ์ฝ๋๋ฅผ ๊ตฌ๋ณํ์ ์ฐ๋ค ๋ณด๋ ํญ์ ๋์ค๋ ์๋ฌ์ฝ๋๋ค์ ์ ํด์ ธ ์์๋ค. ์ด์ ์ด๋ฌํ ์๋ฌ์ ๋ํด ๋งค๋ฒ ์๋ฌ๋ฅผ throwํ๋ ๊ณผ์ ์์ ๊ตณ์ด ๋ฉ์ธ์ง๋ฅผ ํ๋์ฝ๋ฉํ๊ธฐ๋ณด๋จ, ์์ํ์์ผ์ ์ด๋ฅผ importํด์์ ์ฌ์ฉํ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๋ฉด ๋์ค์๋ ์์ธ์ฒ๋ฆฌ๋ฅผ ํ ๋ ํธํด์ง ๊ฒ ๊ฐ์์ ๊ฐ์ ์ ์งํํ๋ค.
- json ๊ตฌ์กฐ ๋ฐ๊พธ๊ธฐ
{
"fileName": "billboard",
"types": {
"id": "number",
"singer": "string",
"year": "number",
"song": "string"
}
}
๋๋ ๊ธฐ์กด ํ์ผ์ ํ์ ์ ๋ค๋ฅธ ๊ตฌ๋ถ์๋ฅผ ๋ถ์ฌ ๊ตฌ๋ถํ๋ ๊ฒ์ ์๋์ ํ์์ ๋ฒ์ด๋๊ธฐ๋ ํ๊ณ , ์๋๋ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๋๊ณ ๊ด๋ฆฌํ๋ค๋ ์ด์ผ๊ธฐ๋ฅผ ๋ค์ด ํ์ ๊ณผ ๊ฐ์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ก ๋๋ ค๊ณ ํ์๋ค. ๊ทธ๋ฌ๋ ์ด๋ฌํ ํ์ ๋ง์ ๋ฐ๋ก ๋๊ธฐ์๋ jsonํ์ผ์ ๋ํด ์คํ๋ ค ๋ญ๋น๊ฐ๋ค๋ ์๊ฐ์ด ๋ค์ด, ๋ด๊ฐ ๋์ค์ ์ฒ๋ฆฌํด์ ์ธ๋งํ ๋ฐ์ดํฐ๋ค์ ๋ฐ๋ก ๋ณด๊ดํ๊ธฐ๋ก ํ์๋ค. ๋ฐ๋ผ์ ๋๋ fileName๊ณผ type์ ๋์์ผ๋ฉฐ, fileName์ ๊ฒฝ์ฐ ํ์ json ํ์ผ์ ์ฝ์ด๋ค์ด์ filename์ ์ฝ๊ฒ ๋ฝ์๋ด์ด ํ์ผ์ ๋ํ ์ฒ๋ฆฌ๊ฐ ๋ณด๋ค ์ฌ์์ง ์ ์๋ค๊ณ ์๊ฐํ์ฌ json๊ตฌ์กฐ๋ฅผ ๊ธฐ์กด ํ์ผ๋ช ์ ๋ณด๊ดํ๋ ๊ฒ๋ณด๋ค๋ ํ ์ด๋ธ์ ์ด๋ฆ์ ๊ธฐ์ตํ์ฌ ํ์ฉํ ์ ์๋๋ก ํ์๋ค. โ