rawsql-ts
Version:
High-performance SQL parser and AST analyzer written in TypeScript. Provides fast parsing and advanced transformation capabilities.
104 lines • 4.77 kB
JavaScript
import { SimpleSelectQuery } from "../models/SelectQuery";
import { LimitClause, OffsetClause } from "../models/Clause";
import { ParameterExpression } from "../models/ValueComponent";
import { SelectQueryParser } from "../parsers/SelectQueryParser";
/**
* SqlPaginationInjector injects pagination (LIMIT/OFFSET) into a SelectQuery model,
* creating LIMIT and OFFSET clauses based on provided pagination options.
*/
export class SqlPaginationInjector {
/**
* Injects pagination as LIMIT/OFFSET clauses into the given query model.
* @param query The SelectQuery to modify
* @param pagination Pagination options containing page number and page size
* @returns The modified SimpleSelectQuery with pagination applied
*/
inject(query, pagination) {
// Validate pagination options
this.validatePaginationOptions(pagination);
// Convert string query to SimpleSelectQuery using SelectQueryParser if needed
if (typeof query === 'string') {
query = SelectQueryParser.parse(query);
}
// Check if query is SimpleSelectQuery
if (!(query instanceof SimpleSelectQuery)) {
throw new Error('Complex queries are not supported for pagination');
}
// Check if query already has LIMIT or OFFSET clauses
if (query.limitClause || query.offsetClause) {
throw new Error('Query already contains LIMIT or OFFSET clause. Use removePagination() first if you want to override existing pagination.');
}
// Calculate offset
const offset = (pagination.page - 1) * pagination.pageSize;
// Create LIMIT clause
const limitClause = new LimitClause(new ParameterExpression('paging_limit', pagination.pageSize));
// Create OFFSET clause (always include for consistent query caching)
const offsetClause = new OffsetClause(new ParameterExpression('paging_offset', offset));
// Create a new query with pagination clauses
return new SimpleSelectQuery({
withClause: query.withClause,
selectClause: query.selectClause,
fromClause: query.fromClause,
whereClause: query.whereClause,
groupByClause: query.groupByClause,
havingClause: query.havingClause,
orderByClause: query.orderByClause,
windowClause: query.windowClause,
limitClause: limitClause,
offsetClause: offsetClause,
fetchClause: query.fetchClause,
forClause: query.forClause,
});
}
/**
* Removes LIMIT and OFFSET clauses from the given query.
* @param query The SelectQuery to modify
* @returns The modified SimpleSelectQuery with pagination removed
*/
static removePagination(query) {
// Convert string query to SimpleSelectQuery using SelectQueryParser if needed
if (typeof query === 'string') {
query = SelectQueryParser.parse(query);
}
// Check if query is SimpleSelectQuery
if (!(query instanceof SimpleSelectQuery)) {
throw new Error('Complex queries are not supported for pagination removal');
}
// Create a new query without LIMIT and OFFSET clauses
return new SimpleSelectQuery({
withClause: query.withClause,
selectClause: query.selectClause,
fromClause: query.fromClause,
whereClause: query.whereClause,
groupByClause: query.groupByClause,
havingClause: query.havingClause,
orderByClause: query.orderByClause,
windowClause: query.windowClause,
limitClause: null, // Remove LIMIT
offsetClause: null, // Remove OFFSET
fetchClause: query.fetchClause,
forClause: query.forClause,
});
}
/**
* Validates pagination options
* @param pagination Pagination options to validate
* @throws Error if validation fails
*/
validatePaginationOptions(pagination) {
if (!pagination) {
throw new Error('Pagination options are required');
}
if (typeof pagination.page !== 'number' || pagination.page < 1) {
throw new Error('Page number must be a positive integer (1 or greater)');
}
if (typeof pagination.pageSize !== 'number' || pagination.pageSize < 1) {
throw new Error('Page size must be a positive integer (1 or greater)');
}
// Optional: Set reasonable upper limit for page size to prevent performance issues
if (pagination.pageSize > 1000) {
throw new Error('Page size cannot exceed 1000 items');
}
}
}
//# sourceMappingURL=SqlPaginationInjector.js.map