UNPKG

sql-to-nosql

Version:

Run SQL quries on your Mongodb database.

110 lines 3.85 kB
import { mappings } from "../config/mapping.mjs"; export const parseQuery = (query) => { const parsedQuery = { command: "select", table: "", columns: [], filters: null, orderBy: null, limit: null, offset: null, }; // for splliting by comma and space const [command, ...rest] = query.split(/, |,| /); const lowerCaseCommand = command.toLowerCase(); if (lowerCaseCommand !== "select") { throw new Error("Only select queries are supported"); } const fromIndex = rest.findIndex((word) => word.toLowerCase() === "from"); if (fromIndex === -1) { throw new Error("Invalid query, missing FROM keyword"); } parsedQuery.table = rest[fromIndex + 1]; parsedQuery.columns = rest.slice(0, fromIndex); const whereIndex = rest.findIndex((word) => word.toLowerCase() === "where"); if (whereIndex !== -1) { parsedQuery.filters = [ { column: rest[whereIndex + 1], operator: rest[whereIndex + 2], // to handle string and number values value: Number(rest[whereIndex + 3]) || // remove quotes from string values String(rest[whereIndex + 3]).replace(/^'(.*)'$/, "$1"), }, ]; } const orderByIndex = rest.findIndex((word) => word.toLowerCase() === "order"); if (orderByIndex !== -1) { // couldn't find index with "order by" coz we splitted by space!! 😶 // ikr, but it works though 🤷 if (rest[orderByIndex + 1].toLowerCase() !== "by") { throw new Error("Invalid query, missing BY keyword"); } parsedQuery.orderBy = { column: rest[orderByIndex + 2], order: ["asc", "desc"].includes(rest[orderByIndex + 3]) ? rest[orderByIndex + 3] : "asc", }; } const limitIndex = rest.findIndex((word) => word.toLowerCase() === "limit"); if (limitIndex !== -1) { parsedQuery.limit = Number(rest[limitIndex + 1]); } const offsetIndex = rest.findIndex((word) => word.toLowerCase() === "offset"); if (offsetIndex !== -1) { parsedQuery.offset = Number(rest[offsetIndex + 1]); } return parsedQuery; }; export const parsedQueryToMongoQuery = (q) => { if (q.command !== "select") { throw new Error("Only select queries are supported"); } const mongoQuery = { collection: q.table, [q.command]: mappings["mongodb"]["commands"][q.command], query: {}, fields: { // coz mongodb by default returns _id _id: 0, }, sort: {}, limit: q.limit, skip: q.offset, }; // Convert parsed columns to document fields if (q.columns) { q.columns.forEach((column) => { if (column === "*") { // If "SELECT *" is used, don't specify fields property return; } if (column === "_id") { mongoQuery.fields["_id"] = 1; } else { mongoQuery.fields[column] = 1; } }); } // Convert parsed filters to MongoDB query if (q.filters) { q.filters.forEach((filter) => { const { column, operator, value } = filter; if (!mongoQuery.query[column]) { mongoQuery.query[column] = {}; } mongoQuery.query[column][mappings["mongodb"]["operators"][operator]] = value; }); } // Convert parsed orderBy to MongoDB sort if (q.orderBy) { const { column, order } = q.orderBy; mongoQuery.sort[column] = order === "asc" ? 1 : -1; } return mongoQuery; }; //# sourceMappingURL=parser.mjs.map