rawsql-ts
Version:
High-performance SQL parser and AST analyzer written in TypeScript. Provides fast parsing and advanced transformation capabilities.
177 lines (175 loc) • 7.13 kB
TypeScript
import { SelectQuery } from "../models/SelectQuery";
import { SortConditions } from "./SqlSortInjector";
import { PaginationOptions } from "./SqlPaginationInjector";
import { JsonMapping } from "./PostgresJsonQueryBuilder";
import { SqlParameterValue } from "../models/ValueComponent";
/**
* Value union accepted for a single filter entry in DynamicQueryBuilder.
*
* @example
* ```typescript
* const options = { filter: { price: { min: 10, max: 100 }, status: ['active', 'pending'] } };
* builder.buildQuery('SELECT * FROM orders', options);
* ```
* Related tests: packages/core/tests/transformers/DynamicQueryBuilder.test.ts
*/
export type FilterConditionValue = SqlParameterValue | SqlParameterValue[] | {
min?: SqlParameterValue;
max?: SqlParameterValue;
like?: string;
ilike?: string;
in?: SqlParameterValue[];
any?: SqlParameterValue[];
'='?: SqlParameterValue;
'>'?: SqlParameterValue;
'<'?: SqlParameterValue;
'>='?: SqlParameterValue;
'<='?: SqlParameterValue;
'!='?: SqlParameterValue;
'<>'?: SqlParameterValue;
or?: {
column: string;
[operator: string]: SqlParameterValue | string;
}[];
and?: {
column: string;
[operator: string]: SqlParameterValue | string;
}[];
column?: string;
};
/**
* Filter conditions for dynamic query building.
*
* Supports both unqualified and qualified column names:
* - Unqualified: `{ name: 'Alice' }` - applies to all columns named 'name'
* - Qualified: `{ 'users.name': 'Bob' }` - applies only to the 'name' column in the 'users' table/alias
* - Hybrid: `{ name: 'Default', 'users.name': 'Override' }` - qualified names take priority over unqualified
*
* @example
* ```typescript
* // Basic usage (backward compatible)
* const filter: FilterConditions = {
* name: 'Alice',
* status: 'active'
* };
*
* // Qualified names for disambiguation in JOINs
* const filter: FilterConditions = {
* 'users.name': 'Alice', // Only applies to users.name
* 'profiles.name': 'Bob' // Only applies to profiles.name
* };
*
* // Hybrid approach
* const filter: FilterConditions = {
* status: 'active', // Applies to all 'status' columns
* 'users.name': 'Alice', // Overrides for users.name specifically
* 'profiles.name': 'Bob' // Overrides for profiles.name specifically
* };
* ```
* Related tests: packages/core/tests/transformers/DynamicQueryBuilder.test.ts
*/
export type FilterConditions = Record<string, FilterConditionValue>;
/**
* Options for dynamic query building
*/
export interface QueryBuildOptions {
/** Filter conditions to inject into WHERE clause */
filter?: FilterConditions;
/** Sort conditions to inject into ORDER BY clause */
sort?: SortConditions;
/** Pagination options to inject LIMIT/OFFSET clauses */
paging?: PaginationOptions;
/** JSON serialization mapping to transform results into hierarchical JSON
* - JsonMapping object: explicit mapping configuration
* - true: auto-load mapping from corresponding .json file
* - false/undefined: no serialization
*/
serialize?: JsonMapping | boolean;
/**
* JSONB usage setting. Must be true (default) for PostgreSQL GROUP BY compatibility.
* Setting to false will throw an error as JSON type cannot be used in GROUP BY clauses.
* @default true
*/
jsonb?: boolean;
}
/**
* DynamicQueryBuilder combines SQL parsing with dynamic condition injection (filters, sorts, paging, JSON serialization).
*
* Key behaviours verified in packages/core/tests/transformers/DynamicQueryBuilder.test.ts:
* - Preserves the input SQL when no options are supplied.
* - Applies filter, sort, and pagination in a deterministic order.
* - Supports JSON serialization for hierarchical projections.
*/
export declare class DynamicQueryBuilder {
private tableColumnResolver?;
/**
* Creates a new DynamicQueryBuilder instance
* @param tableColumnResolver Optional function to resolve table columns for wildcard queries
*/
constructor(tableColumnResolver?: (tableName: string) => string[]);
/**
* Builds a SelectQuery from SQL content with dynamic conditions.
* This is a pure function that does not perform any I/O operations.
* @param sqlContent Raw SQL string to parse and modify
* @param options Dynamic conditions to apply (filter, sort, paging, serialize)
* @returns Modified SelectQuery with all dynamic conditions applied
* @example
* ```typescript
* const builder = new DynamicQueryBuilder();
* const query = builder.buildQuery(
* 'SELECT id, name FROM users WHERE active = true',
* {
* filter: { status: 'premium' },
* sort: { created_at: { desc: true } },
* paging: { page: 2, pageSize: 10 },
* serialize: { rootName: 'user', rootEntity: { id: 'user', name: 'User', columns: { id: 'id', name: 'name' } }, nestedEntities: [] }
* }
* );
* ```
*/
buildQuery(sqlContent: string, options?: QueryBuildOptions): SelectQuery;
/**
* Builds a SelectQuery with only filtering applied.
* Convenience method for when you only need dynamic WHERE conditions.
*
* @param sqlContent Raw SQL string to parse and modify
* @param filter Filter conditions to apply
* @returns Modified SelectQuery with filter conditions applied
*/
buildFilteredQuery(sqlContent: string, filter: FilterConditions): SelectQuery;
/**
* Builds a SelectQuery with only sorting applied.
* Convenience method for when you only need dynamic ORDER BY clauses.
*
* @param sqlContent Raw SQL string to parse and modify
* @param sort Sort conditions to apply
* @returns Modified SelectQuery with sort conditions applied
*/
buildSortedQuery(sqlContent: string, sort: SortConditions): SelectQuery; /**
* Builds a SelectQuery with only pagination applied.
* Convenience method for when you only need LIMIT/OFFSET clauses.
*
* @param sqlContent Raw SQL string to parse and modify
* @param paging Pagination options to apply
* @returns Modified SelectQuery with pagination applied
*/
buildPaginatedQuery(sqlContent: string, paging: PaginationOptions): SelectQuery;
/**
* Builds a SelectQuery with only JSON serialization applied.
* Convenience method for when you only need hierarchical JSON transformation.
*
* @param sqlContent Raw SQL string to parse and modify
* @param serialize JSON mapping configuration to apply
* @returns Modified SelectQuery with JSON serialization applied
*/
buildSerializedQuery(sqlContent: string, serialize: JsonMapping): SelectQuery;
/**
* Validates SQL content by attempting to parse it.
* Useful for testing SQL validity without applying any modifications.
*
* @param sqlContent Raw SQL string to validate
* @returns true if SQL is valid, throws error if invalid
* @throws Error if SQL cannot be parsed
*/
validateSql(sqlContent: string): boolean;
}