SqlValidator

A utility object that provides functionality for SQL validation and schema handling. This includes methods for checking SQL query syntax, validating against schemas, managing schemas from definition files, and ensuring data type consistency during validation.

Types

Link copied to clipboard
data class ColumnDef(val name: String, val type: String)
Link copied to clipboard
data class MigrationTable(columns: List<SqlValidator.ColumnDef>) : AbstractTable
Link copied to clipboard

The kind of SQL statement a repository method prefix expects.

Link copied to clipboard
data class TableDef(val name: String, val columns: MutableList<SqlValidator.ColumnDef>)

Functions

Link copied to clipboard
fun dropOrderBy(stmt: Statement, sql: String): String

Removes an ORDER BY clause that has no effect on the result of a scalar method (exists*, count*) — ordering rows the query never returns individually is pure overhead for the database. Returns the SQL unchanged when there is no ORDER BY or the statement is not a plain select.

Link copied to clipboard
fun expandReturningStar(stmt: Statement, sql: String, tableName: String, columnNames: List<String>): String

Rewrites a bare RETURNING * on a write over the entity's own table into the entity's explicit columns, mirroring expandSelectStar. Returns the SQL unchanged for anything else (a non-write, a write against a different table, or an explicit RETURNING column list).

Link copied to clipboard
fun expandSelectStar(stmt: Statement, sql: String, tableName: String, columnNames: List<String>): String

Rewrites a bare SELECT * over the entity's own table into the entity's explicit columns. Returns the SQL unchanged for anything else (joins, a different table, SELECT count(*), an explicit list).

Link copied to clipboard
fun loadSchema(path: String)

Loads SQL schema definitions from the specified directory, processes each .sql file encountered, and constructs a representation of the database schema consisting of tables and their columns.

Link copied to clipboard
fun rejectGroupingInScalar(fn: String, stmt: Statement)

Rejects a GROUP BY / HAVING clause in a method that reads a single scalar row (count*, findOne*, exists*). Such a query returns one row per group, but these methods only read the first row — so grouping would silently yield the wrong result. Non-plain selects are skipped.

Link copied to clipboard
fun rejectStackedStatements(fn: String, statements: List<Statement>)

Rejects a @Query value that contains more than one SQL statement (a stacked-query safety guard). Malformed SQL is ignored here — it is reported by validateQuerySyntax.

Link copied to clipboard
fun toExistsQuery(stmt: Statement, sql: String, tableName: String): String

Wraps a plain SELECT ... FROM <entity table> WHERE ... into SELECT EXISTS(SELECT 1 FROM ...) for exists* methods. If the query is not a plain select over the entity table (e.g. the user already wrote SELECT EXISTS(...), which has no FROM), it is returned unchanged.

Link copied to clipboard
fun validateColumnsExist(fn: String, stmt: Statement, tableName: String, columnNames: Set<String>)

Validates that every column referenced by a single-table @Query exists on the entity. Multi-table queries (joins, subselects, or a different FROM table) are skipped to avoid false positives.

Link copied to clipboard
fun validateCountProjection(fn: String, stmt: Statement)

Validates that a count* method selects a single count(...) aggregate (rather than, say, *).

Link copied to clipboard
fun validateProjection(fn: String, stmt: Statement, columnNames: Set<String>)

Validates that a find* method whose result is bound by the generated row mapper selects every entity column (or SELECT *). A partial projection would leave the mapper without a column at runtime. Multi-table queries and non-plain selects are skipped.

Link copied to clipboard

Validates the provided SQL query schema against Calcite's SQL parser and validator. Optionally applies custom literal type checks if the VALIDATE_LITERAL_TYPES flag is enabled.

Link copied to clipboard
fun validateQuerySyntax(fn: String, sql: String, reportErrors: Boolean = true): List<Statement>

Parses sql and returns the parsed statement(s), so the result can be reused by the structural checks (rejectStackedStatements, validateColumnsExist, expandSelectStar) instead of re-parsing.

Link copied to clipboard
fun validateReturningColumns(fn: String, stmt: Statement, columnNames: Set<String>)

Validates that a RETURNING clause references only columns that exist on the entity.

Link copied to clipboard
fun validateStatementKind(fn: String, stmt: Statement, expected: SqlValidator.StatementKind)

Validates that the statement kind matches the one implied by the method prefix (e.g. find* must be a SELECT, delete* a DELETE, execute* a write).

Link copied to clipboard
fun validateTable(fn: String, stmt: Statement, tableName: String)

Validates that a single-table @Query targets the repository entity's own table. A FROM that is a subselect (or a non-CRUD statement) is skipped.

Link copied to clipboard
fun withRowLimit(stmt: Statement, sql: String, rowCount: Long): String

Appends a LIMIT [rowCount] to a SELECT that has none, so findOne* methods fetch at most a couple of rows while still detecting a multi-row result. Returns the SQL unchanged for anything that already has a limit or is not a plain select. LIMIT n is portable across all supported dialects (PostgreSQL, MySQL, SQLite).