QueryDslMarker
Specialized DSL marker annotation for Wow query domain-specific operations.
This annotation provides fine-grained control over DSL contexts within the Wow query framework, specifically targeting query-related domain operations such as filtering, projection, and aggregation. It extends the base @DslMarker functionality to create isolated scopes for different query construction phases, ensuring type-safe and context-aware query building.
Purpose
The @QueryDslMarker annotation serves as a specialized marker for query DSL components that need stricter isolation than the general @QueryDsl marker. It is particularly useful for:
Complex query composition with multiple nested contexts
Domain-specific query operations (filtering, joining, aggregation)
Preventing method leakage between closely related but distinct DSL phases
Maintaining clear boundaries in advanced query scenarios
Scope and Application
Apply this marker to DSL interfaces and classes that handle:
Filter DSLs: Where clauses, condition building, predicate composition
Projection DSLs: Select clauses, field specification, result shaping
Aggregation DSLs: Group by operations, aggregate functions, statistical queries
Join DSLs: Relationship traversal, multi-entity queries
How It Works
@QueryDslMarker leverages Kotlin's @DslMarker mechanism to restrict implicit this references in lambda expressions. When applied to DSL classes, it prevents methods from outer contexts from being implicitly accessible, creating clean separation between different query operations.
Usage Examples
Filter DSL with Strict Isolation
@QueryDslMarker
interface FilterDsl {
fun where(init: ConditionDsl.() -> Unit): FilterDsl
fun having(init: AggregateConditionDsl.() -> Unit): FilterDsl
}
@QueryDslMarker
interface ConditionDsl {
infix fun String.eq(value: Any): Condition
infix fun String.gt(value: Any): Condition
// Methods from FilterDsl not accessible here
}Projection DSL
@QueryDslMarker
interface ProjectionDsl {
fun select(vararg fields: String): ProjectionDsl
fun exclude(vararg fields: String): ProjectionDsl
fun include(init: FieldSelectorDsl.() -> Unit): ProjectionDsl
}
@QueryDslMarker
interface FieldSelectorDsl {
fun field(name: String): FieldSelector
fun nested(path: String, init: FieldSelectorDsl.() -> Unit): FieldSelector
// ProjectionDsl methods not accessible here
}Query Composition Example
val complexQuery = query {
filter { // FilterDsl context
where { // ConditionDsl context
"status" eq "active" // ConditionDsl methods only
"age" gt 18
// filter.where() not accessible due to @QueryDslMarker
}
having { // AggregateConditionDsl context
count("orders") gt 5 // Aggregate methods only
// filter.having() not accessible
}
}
project { // ProjectionDsl context
select("name", "email") // ProjectionDsl methods only
include { // FieldSelectorDsl context
field("profile")
// project.select() not accessible
}
}
}Benefits
Enhanced Type Safety: Stricter isolation prevents context confusion
Domain Clarity: Clear separation of query operation concerns
Composability: Safe nesting of related but distinct DSL contexts
Refactoring Safety: Changes to one DSL context don't affect others
IDE Experience: Precise code completion and error detection
Implementation Guidelines
Apply to DSL interfaces handling specific query domains
Use in conjunction with
@QueryDslfor layered isolationConsider the granularity of DSL contexts when applying
Test DSL composition to ensure proper isolation
Relationship to QueryDsl
While @QueryDsl provides general DSL isolation, @QueryDslMarker offers specialized isolation for complex query scenarios requiring multiple nested contexts. Use @QueryDsl for basic query construction and @QueryDslMarker for advanced domain-specific operations.
Since
1.0.0
See also
for general query DSL isolation
for the underlying Kotlin compiler support
for condition DSL implementations
for projection DSL implementations