UNPKG

@kuindji/sql-type-parser

Version:
128 lines 11.6 kB
/** * INSERT Query Validator * * This module provides comprehensive validation for INSERT queries. * It validates: * - Table existence in schema * - Column existence in target table * - Value count matches column count * - RETURNING clause column validation */ import type { SQLInsertQuery, InsertClause, InsertColumnList, InsertColumnRef, InsertValuesClause, InsertSelectClause, InsertValueRow, ReturningClause, OnConflictClause, ConflictUpdateSet } from "./ast.js"; import type { TableRef, UnboundColumnRef } from "../common/ast.js"; import type { ParseError, HasTemplateHoles } from "../common/utils.js"; import type { DatabaseSchema, GetDefaultSchema } from "../common/schema.js"; import type { ParseInsertSQL } from "./parser.js"; export type { MatchError } from "../common/utils.js"; export type { DatabaseSchema } from "../common/schema.js"; /** * Options for controlling INSERT query validation depth */ export type ValidateInsertOptions = { /** * Whether to validate the value count matches column count * @default true */ validateValueCount?: boolean; /** * Whether to validate RETURNING clause columns * @default true */ validateReturning?: boolean; }; /** * Default validation options - full validation enabled */ type DefaultValidateOptions = { validateValueCount: true; validateReturning: true; }; /** * Validate an INSERT query against a schema * * Returns true if valid, or an error message if invalid. * For dynamic queries (non-literal strings), returns true (can't validate at compile time). * * @param SQL - The SQL query string to validate * @param Schema - The database schema to validate against * @param Options - Validation options (optional, defaults to full validation) */ export type ValidateInsertSQL<SQL extends string, Schema extends DatabaseSchema, Options extends ValidateInsertOptions = DefaultValidateOptions> = HasTemplateHoles<SQL> extends true ? true : ParseInsertSQL<SQL> extends infer Parsed ? Parsed extends ParseError<infer E> ? E : Parsed extends SQLInsertQuery<infer Query> ? ValidateInsertClause<Query, Schema, Options> : "Failed to parse query" : never; /** * Validate an INSERT clause */ type ValidateInsertClause<Insert extends InsertClause, Schema extends DatabaseSchema, Options extends ValidateInsertOptions = DefaultValidateOptions> = Insert extends InsertClause<infer Table, infer Columns, infer Source, infer OnConflict, infer Returning> ? ValidateTable<Table, Schema> extends infer TableResult ? TableResult extends true ? ValidateColumnsExist<Table, Columns, Schema> extends infer ColResult ? ColResult extends true ? ValidateSource<Source, Table, Columns, Schema, Options> extends infer SourceResult ? SourceResult extends true ? ValidateOnConflict<OnConflict, Table, Schema> extends infer ConflictResult ? ConflictResult extends true ? ValidateReturningClause<Returning, Table, Schema, Options> : ConflictResult : "ON CONFLICT validation failed" : SourceResult : "Source validation failed" : ColResult : "Column validation failed" : TableResult : "Table validation failed" : "Invalid INSERT clause"; /** * Validate that the target table exists in the schema */ type ValidateTable<Table extends TableRef, Schema extends DatabaseSchema> = Table extends TableRef<infer TableName, infer _Alias, infer TableSchema> ? ResolveTableInSchema<TableName, TableSchema, Schema> : `Invalid table reference`; /** * Resolve a table in the database schema */ type ResolveTableInSchema<TableName extends string, TableSchema extends string | undefined, Schema extends DatabaseSchema> = TableSchema extends undefined ? GetDefaultSchema<Schema> extends infer DefaultSchema extends string ? DefaultSchema extends keyof Schema["schemas"] ? TableName extends keyof Schema["schemas"][DefaultSchema] ? true : `Table '${TableName}' not found in default schema '${DefaultSchema}'` : `Default schema not found` : `Cannot determine default schema` : TableSchema extends string ? TableSchema extends keyof Schema["schemas"] ? TableName extends keyof Schema["schemas"][TableSchema] ? true : `Table '${TableName}' not found in schema '${TableSchema}'` : `Schema '${TableSchema}' not found` : `Invalid schema type`; /** * Validate that all specified columns exist in the target table */ type ValidateColumnsExist<Table extends TableRef, Columns extends InsertColumnList | undefined, Schema extends DatabaseSchema> = Columns extends undefined ? true : Columns extends InsertColumnList<infer ColList> ? ValidateColumnList<ColList, Table, Schema> : true; /** * Validate a list of columns */ type ValidateColumnList<Columns extends InsertColumnRef[], Table extends TableRef, Schema extends DatabaseSchema> = Columns extends [infer First, ...infer Rest] ? First extends InsertColumnRef<infer ColName> ? ValidateColumnExists<ColName, Table, Schema> extends infer Result ? Result extends true ? Rest extends InsertColumnRef[] ? ValidateColumnList<Rest, Table, Schema> : true : Result : "Column validation failed" : true : true; /** * Validate a single column exists in the table */ type ValidateColumnExists<ColumnName extends string, Table extends TableRef, Schema extends DatabaseSchema> = Table extends TableRef<infer TableName, infer _Alias, infer TableSchema> ? TableSchema extends undefined ? GetDefaultSchema<Schema> extends infer DefaultSchema extends string ? DefaultSchema extends keyof Schema["schemas"] ? TableName extends keyof Schema["schemas"][DefaultSchema] ? ColumnName extends keyof Schema["schemas"][DefaultSchema][TableName] ? true : `Column '${ColumnName}' not found in table '${TableName}'` : `Table '${TableName}' not found` : `Default schema not found` : `Cannot determine default schema` : TableSchema extends string ? TableSchema extends keyof Schema["schemas"] ? TableName extends keyof Schema["schemas"][TableSchema] ? ColumnName extends keyof Schema["schemas"][TableSchema][TableName] ? true : `Column '${ColumnName}' not found in table '${TableSchema}.${TableName}'` : `Table '${TableName}' not found in schema '${TableSchema}'` : `Schema '${TableSchema}' not found` : `Invalid schema type` : `Invalid table reference`; /** * Validate INSERT source (VALUES or SELECT) */ type ValidateSource<Source, Table extends TableRef, Columns extends InsertColumnList | undefined, Schema extends DatabaseSchema, Options extends ValidateInsertOptions> = Source extends InsertValuesClause<infer Rows> ? Options["validateValueCount"] extends false ? true : ValidateValueRows<Rows, Table, Columns, Schema> : Source extends InsertSelectClause ? true : true; /** * Validate value rows have correct count */ type ValidateValueRows<Rows extends InsertValueRow[], Table extends TableRef, Columns extends InsertColumnList | undefined, Schema extends DatabaseSchema> = Rows extends [infer First, ...infer Rest] ? First extends InsertValueRow<infer Values> ? ValidateValueCount<Values, Table, Columns, Schema> extends infer Result ? Result extends true ? Rest extends InsertValueRow[] ? ValidateValueRows<Rest, Table, Columns, Schema> : true : Result : "Value validation failed" : true : true; /** * Validate value count matches column count * If no columns specified, count must match table column count */ type ValidateValueCount<Values extends unknown[], Table extends TableRef, Columns extends InsertColumnList | undefined, Schema extends DatabaseSchema> = Columns extends InsertColumnList<infer ColList> ? Values["length"] extends ColList["length"] ? true : `Value count (${Values["length"]}) does not match column count (${ColList["length"]})` : true; /** * Validate ON CONFLICT clause */ type ValidateOnConflict<OnConflict, Table extends TableRef, Schema extends DatabaseSchema> = OnConflict extends undefined ? true : OnConflict extends OnConflictClause<infer Target, infer _Action, infer Updates, infer _Where> ? ValidateConflictTarget<Target, Table, Schema> extends infer TargetResult ? TargetResult extends true ? ValidateConflictUpdates<Updates, Table, Schema> : TargetResult : "Conflict target validation failed" : true; /** * Validate conflict target columns exist */ type ValidateConflictTarget<Target, Table extends TableRef, Schema extends DatabaseSchema> = Target extends undefined ? true : Target extends { columns: infer Cols; } ? Cols extends string[] ? ValidateStringColumns<Cols, Table, Schema> : true : true; /** * Validate string column names */ type ValidateStringColumns<Cols extends string[], Table extends TableRef, Schema extends DatabaseSchema> = Cols extends [infer First extends string, ...infer Rest extends string[]] ? ValidateColumnExists<First, Table, Schema> extends infer Result ? Result extends true ? ValidateStringColumns<Rest, Table, Schema> : Result : "Column validation failed" : true; /** * Validate conflict update SET clauses */ type ValidateConflictUpdates<Updates, Table extends TableRef, Schema extends DatabaseSchema> = Updates extends undefined ? true : Updates extends ConflictUpdateSet[] ? ValidateUpdateSetList<Updates, Table, Schema> : true; /** * Validate list of SET clauses */ type ValidateUpdateSetList<Updates extends ConflictUpdateSet[], Table extends TableRef, Schema extends DatabaseSchema> = Updates extends [infer First, ...infer Rest] ? First extends ConflictUpdateSet<infer Col, infer _Val> ? ValidateColumnExists<Col, Table, Schema> extends infer Result ? Result extends true ? Rest extends ConflictUpdateSet[] ? ValidateUpdateSetList<Rest, Table, Schema> : true : Result : "SET column validation failed" : true : true; /** * Validate RETURNING clause */ type ValidateReturningClause<Returning, Table extends TableRef, Schema extends DatabaseSchema, Options extends ValidateInsertOptions> = Options["validateReturning"] extends false ? true : Returning extends undefined ? true : Returning extends ReturningClause<infer Cols> ? Cols extends "*" ? true : Cols extends UnboundColumnRef[] ? ValidateReturningColumns<Cols, Table, Schema> : true : true; /** * Validate RETURNING column list */ type ValidateReturningColumns<Cols extends UnboundColumnRef[], Table extends TableRef, Schema extends DatabaseSchema> = Cols extends [infer First, ...infer Rest] ? First extends UnboundColumnRef<infer ColName> ? ValidateColumnExists<ColName, Table, Schema> extends infer Result ? Result extends true ? Rest extends UnboundColumnRef[] ? ValidateReturningColumns<Rest, Table, Schema> : true : Result : "RETURNING column validation failed" : true : true; /** * Check if an INSERT query is valid * Returns true if valid, error message string if invalid */ export type IsValidInsert<SQL extends string, Schema extends DatabaseSchema> = ValidateInsertSQL<SQL, Schema> extends true ? true : false; /** * Get the table columns that would be affected by an INSERT * Returns the table's column type definition */ export type GetInsertTableColumns<SQL extends string, Schema extends DatabaseSchema> = ParseInsertSQL<SQL> extends SQLInsertQuery<infer Query> ? Query extends InsertClause<infer Table, infer _Cols, infer _Source, infer _Conflict, infer _Return> ? Table extends TableRef<infer TableName, infer _Alias, infer TableSchema> ? TableSchema extends undefined ? GetDefaultSchema<Schema> extends infer DefaultSchema extends string ? DefaultSchema extends keyof Schema["schemas"] ? TableName extends keyof Schema["schemas"][DefaultSchema] ? Schema["schemas"][DefaultSchema][TableName] : never : never : never : TableSchema extends keyof Schema["schemas"] ? TableName extends keyof Schema["schemas"][TableSchema] ? Schema["schemas"][TableSchema][TableName] : never : never : never : never : never; //# sourceMappingURL=validator.d.ts.map