UNPKG

rawsql-ts

Version:

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

153 lines 7.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SqlSortInjector = void 0; const SelectQuery_1 = require("../models/SelectQuery"); const SelectableColumnCollector_1 = require("./SelectableColumnCollector"); const Clause_1 = require("../models/Clause"); const SelectQueryParser_1 = require("../parsers/SelectQueryParser"); /** * SqlSortInjector injects sort conditions into a SelectQuery model, * creating ORDER BY clauses based on provided sort conditions. */ class SqlSortInjector { constructor(tableColumnResolver) { this.tableColumnResolver = tableColumnResolver; } /** * Removes ORDER BY clause from the given query. * @param query The SelectQuery to modify * @returns The modified SimpleSelectQuery with ORDER BY clause removed */ static removeOrderBy(query) { // Convert string query to SimpleSelectQuery using SelectQueryParser if needed if (typeof query === 'string') { query = SelectQueryParser_1.SelectQueryParser.parse(query); } // Check if query is SimpleSelectQuery if (!(query instanceof SelectQuery_1.SimpleSelectQuery)) { throw new Error('Complex queries are not supported for ORDER BY removal'); } // Create a new query without ORDER BY clause return new SelectQuery_1.SimpleSelectQuery({ withClause: query.withClause, selectClause: query.selectClause, fromClause: query.fromClause, whereClause: query.whereClause, groupByClause: query.groupByClause, havingClause: query.havingClause, orderByClause: null, // Remove ORDER BY windowClause: query.windowClause, limitClause: query.limitClause, offsetClause: query.offsetClause, fetchClause: query.fetchClause, forClause: query.forClause, }); } /** * Injects sort conditions as ORDER BY clauses into the given query model. * Appends to existing ORDER BY clause if present. * @param query The SelectQuery to modify * @param sortConditions A record of column names and sort conditions * @returns The modified SimpleSelectQuery */ inject(query, sortConditions) { // Convert string query to SimpleSelectQuery using SelectQueryParser if needed if (typeof query === 'string') { query = SelectQueryParser_1.SelectQueryParser.parse(query); } // Check if query is SimpleSelectQuery if (!(query instanceof SelectQuery_1.SimpleSelectQuery)) { throw new Error('Complex queries are not supported for sorting'); } // Collect available columns including all JOIN table columns for sorting const collector = new SelectableColumnCollector_1.SelectableColumnCollector(this.tableColumnResolver, false, // includeWildCard SelectableColumnCollector_1.DuplicateDetectionMode.FullName, // Use FullName to preserve JOIN table columns { upstream: true } // Enable upstream collection for JOIN table sorting ); const availableColumns = collector.collect(query); // Validate that all specified columns exist for (const columnName of Object.keys(sortConditions)) { const columnEntry = availableColumns.find(item => item.name === columnName); if (!columnEntry) { throw new Error(`Column or alias '${columnName}' not found in current query`); } } // Build new ORDER BY items const newOrderByItems = []; for (const [columnName, condition] of Object.entries(sortConditions)) { const columnEntry = availableColumns.find(item => item.name === columnName); if (!columnEntry) continue; // Should not happen due to validation above const columnRef = columnEntry.value; // Validate condition this.validateSortCondition(columnName, condition); // Determine sort direction let sortDirection; if (condition.desc) { sortDirection = Clause_1.SortDirection.Descending; } else { sortDirection = Clause_1.SortDirection.Ascending; // Default to ASC } // Determine nulls position let nullsPosition = null; if (condition.nullsFirst) { nullsPosition = Clause_1.NullsSortDirection.First; } else if (condition.nullsLast) { nullsPosition = Clause_1.NullsSortDirection.Last; } // Create OrderByItem const orderByItem = new Clause_1.OrderByItem(columnRef, sortDirection, nullsPosition); newOrderByItems.push(orderByItem); } // Combine with existing ORDER BY clause if present let finalOrderByItems = []; if (query.orderByClause) { // Append to existing ORDER BY finalOrderByItems = [...query.orderByClause.order, ...newOrderByItems]; } else { // Create new ORDER BY finalOrderByItems = newOrderByItems; } // Create new OrderByClause const newOrderByClause = finalOrderByItems.length > 0 ? new Clause_1.OrderByClause(finalOrderByItems) : null; // Create new query with updated ORDER BY clause return new SelectQuery_1.SimpleSelectQuery({ withClause: query.withClause, selectClause: query.selectClause, fromClause: query.fromClause, whereClause: query.whereClause, groupByClause: query.groupByClause, havingClause: query.havingClause, orderByClause: newOrderByClause, windowClause: query.windowClause, limitClause: query.limitClause, offsetClause: query.offsetClause, fetchClause: query.fetchClause, forClause: query.forClause, }); } /** * Validates sort condition for a column */ validateSortCondition(columnName, condition) { // Check for conflicting sort directions if (condition.asc && condition.desc) { throw new Error(`Conflicting sort directions for column '${columnName}': both asc and desc specified`); } // Check for conflicting nulls positions if (condition.nullsFirst && condition.nullsLast) { throw new Error(`Conflicting nulls positions for column '${columnName}': both nullsFirst and nullsLast specified`); } // Check if at least one option is specified if (!condition.asc && !condition.desc && !condition.nullsFirst && !condition.nullsLast) { throw new Error(`Empty sort condition for column '${columnName}': at least one sort option must be specified`); } } } exports.SqlSortInjector = SqlSortInjector; //# sourceMappingURL=SqlSortInjector.js.map