UNPKG

rawsql-ts

Version:

[beta]High-performance SQL parser and AST analyzer written in TypeScript. Provides fast parsing and advanced transformation capabilities.

122 lines 5.86 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.InsertQuerySelectValuesConverter = void 0; const InsertQuery_1 = require("../models/InsertQuery"); const ValuesQuery_1 = require("../models/ValuesQuery"); const SimpleSelectQuery_1 = require("../models/SimpleSelectQuery"); const BinarySelectQuery_1 = require("../models/BinarySelectQuery"); const Clause_1 = require("../models/Clause"); const ValueComponent_1 = require("../models/ValueComponent"); /** * Utility to convert INSERT ... VALUES statements into INSERT ... SELECT UNION ALL form and vice versa. * Enables easier column-by-column comparison across multi-row inserts. */ class InsertQuerySelectValuesConverter { /** * Converts an INSERT query that uses VALUES into an equivalent INSERT ... SELECT UNION ALL form. * The original InsertQuery remains untouched; the returned InsertQuery references cloned structures. */ static toSelectUnion(insertQuery) { const valuesQuery = insertQuery.selectQuery; if (!(valuesQuery instanceof ValuesQuery_1.ValuesQuery)) { throw new Error("InsertQuery selectQuery is not a VALUES query."); } if (!valuesQuery.tuples.length) { throw new Error("VALUES query does not contain any tuples."); } const columns = insertQuery.insertClause.columns; if (!columns || columns.length === 0) { throw new Error("Cannot convert to SELECT form without explicit column list."); } const columnNames = columns.map(col => col.name); const selectQueries = valuesQuery.tuples.map(tuple => { if (tuple.values.length !== columnNames.length) { throw new Error("Tuple value count does not match column count."); } const items = columnNames.map((name, idx) => new Clause_1.SelectItem(tuple.values[idx], name)); const selectClause = new Clause_1.SelectClause(items); return new SimpleSelectQuery_1.SimpleSelectQuery({ selectClause }); }); let combined = selectQueries[0]; for (let i = 1; i < selectQueries.length; i++) { if (combined instanceof SimpleSelectQuery_1.SimpleSelectQuery) { combined = combined.toUnionAll(selectQueries[i]); } else if (combined instanceof BinarySelectQuery_1.BinarySelectQuery) { combined.appendSelectQuery("union all", selectQueries[i]); } else { throw new Error("Unsupported SelectQuery type during UNION ALL construction."); } } return new InsertQuery_1.InsertQuery({ withClause: insertQuery.withClause, insertClause: insertQuery.insertClause, selectQuery: combined, returning: insertQuery.returningClause }); } /** * Converts an INSERT query that leverages SELECT statements (with optional UNION ALL) * into an equivalent INSERT ... VALUES representation. */ static toValues(insertQuery) { const columns = insertQuery.insertClause.columns; if (!columns || columns.length === 0) { throw new Error("Cannot convert to VALUES form without explicit column list."); } if (!insertQuery.selectQuery) { throw new Error("InsertQuery does not have a selectQuery to convert."); } const columnNames = columns.map(col => col.name); const simpleQueries = this.flattenSelectQueries(insertQuery.selectQuery); if (!simpleQueries.length) { throw new Error("No SELECT components found to convert."); } const tuples = simpleQueries.map(query => { var _a, _b; if (query.fromClause || (query.whereClause && query.whereClause.condition)) { throw new Error("SELECT queries with FROM or WHERE clauses cannot be converted to VALUES."); } const valueMap = new Map(); for (const item of query.selectClause.items) { const identifier = (_b = (_a = item.identifier) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : null; if (!identifier) { throw new Error("Each SELECT item must have an alias matching target columns."); } if (!valueMap.has(identifier)) { valueMap.set(identifier, item.value); } } const rowValues = columnNames.map(name => { const value = valueMap.get(name); if (!value) { throw new Error(`Column '${name}' is not provided by the SELECT query.`); } return value; }); return new ValueComponent_1.TupleExpression(rowValues); }); const valuesQuery = new ValuesQuery_1.ValuesQuery(tuples, columnNames); return new InsertQuery_1.InsertQuery({ withClause: insertQuery.withClause, insertClause: insertQuery.insertClause, selectQuery: valuesQuery, returning: insertQuery.returningClause }); } static flattenSelectQueries(selectQuery) { if (selectQuery instanceof SimpleSelectQuery_1.SimpleSelectQuery) { return [selectQuery]; } if (selectQuery instanceof BinarySelectQuery_1.BinarySelectQuery) { return [ ...this.flattenSelectQueries(selectQuery.left), ...this.flattenSelectQueries(selectQuery.right) ]; } throw new Error("Unsupported SelectQuery subtype for conversion."); } } exports.InsertQuerySelectValuesConverter = InsertQuerySelectValuesConverter; //# sourceMappingURL=InsertQuerySelectValuesConverter.js.map