Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions LIMIT_EXAMPLE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Implementación del Operador LIMIT

## Descripción

Se ha implementado exitosamente el operador LIMIT para la clase QuerySelect, permitiendo limitar el número de filas devueltas en una consulta SELECT.

## Características implementadas

1. **Clase Limit**: Se creó una nueva clase `Limit` en el paquete `operator` que maneja los parámetros de límite y offset.

2. **Soporte en QuerySelect**: Se agregó soporte completo para LIMIT en la clase QuerySelect y su QueryBuilder.

3. **Métodos disponibles**:
- `limit(count: Int)`: Limita el número de filas a devolver
- `limit(count: Int, offset: Int?)`: Limita el número de filas con un offset opcional
- `limit(limitOperator: Limit)`: Acepta un objeto Limit directamente

## Ejemplos de uso

### Uso básico con Builder
```kotlin
val query = QuerySelect.builder("users")
.where(SQLOperator.Equals("status", "active"))
.limit(10)
.build()

// Genera: SELECT * FROM users WHERE status = 'active' LIMIT 10
```

### Uso con offset
```kotlin
val query = QuerySelect.builder("users")
.where(SQLOperator.Equals("status", "active"))
.limit(10, 5)
.build()

// Genera: SELECT * FROM users WHERE status = 'active' LIMIT 10 OFFSET 5
```

### Uso con objeto Limit
```kotlin
val limitOperator = Limit(count = 10, offset = 5)
val query = QuerySelect.builder("users")
.where(SQLOperator.Equals("status", "active"))
.limit(limitOperator)
.build()

// Genera: SELECT * FROM users WHERE status = 'active' LIMIT 10 OFFSET 5
```

### Encadenamiento de métodos
```kotlin
val query = QuerySelect.builder("users")
.where(SQLOperator.Equals("status", "active"))
.and("age", SQLOperator.GreaterThan("age", 18))
.orderBy(OrderBy.Desc("created_at"))
.limit(20)
.build()

// Genera: SELECT * FROM users WHERE status = 'active' AND age > 18
// ORDER BY created_at DESC
// LIMIT 20
```

### Modificación de límite en consulta existente
```kotlin
val query = QuerySelect.builder("users")
.where(SQLOperator.Equals("status", "active"))
.build()

// Agregar límite después de crear la consulta
query.limit(15, 10)

// Genera: SELECT * FROM users WHERE status = 'active' LIMIT 15 OFFSET 10
```

## Validaciones implementadas

La clase Limit incluye validaciones para garantizar que:
- El count debe ser no negativo
- El offset (si se proporciona) debe ser no negativo

## Orden de ejecución SQL

La implementación respeta el orden estándar de SQL:
1. SELECT campos
2. FROM tabla
3. WHERE condiciones
4. ORDER BY (si existe)
5. LIMIT (si existe)

Esta implementación permite crear consultas SQL complejas con paginación de manera fluida y manteniendo la consistencia con el resto del framework.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ Diseñada para integrarse perfectamente con la base de datos de Android y Room a
- [🔗 Integración con Room](#-integración-con-room)
- [📝 Ejemplos Avanzados](#-ejemplos-avanzados)
- [🤝 Contribuir](#-contribuir)
- [📄 Licencia](#-licencia)

---

Expand Down Expand Up @@ -92,6 +91,10 @@ val selectQuery = QuerySelect.builder("users")
.and("status", SQLOperator.Equals("status", "active"))
.setFields("name", "email")
.build()
// Agrega un límite de 10 resultados
selectQuery.limit(10)
// Agrega un offset
selectQuery.limit(10, 5)

val sqlString = selectQuery.asSql()
```
Expand Down
Empty file modified gradlew
100644 → 100755
Empty file.
13 changes: 13 additions & 0 deletions query/src/main/java/com/blipblipcode/query/InnerJoint.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.blipblipcode.query

import com.blipblipcode.query.operator.OrderBy
import com.blipblipcode.query.operator.SQLOperator

/**
* Represents a SQL INNER JOIN query construct.
Expand All @@ -17,6 +18,18 @@ class InnerJoint private constructor(

private var orderBy: OrderBy? = null

override fun getSqlOperators(): List<SQLOperator<*>> {
return queries.flatMap { it.getSqlOperators() }
}

override fun getTableName(): String {
return queries.joinToString(", ") { it.getTableName() }
}

override fun getSqlOperation(key: String): SQLOperator<*>? {
return queries.flatMap { it.getSqlOperators() }.firstOrNull { it.column.equals(key, ignoreCase = true) }
}

/**
* Generates the SQL string for the INNER JOIN statement.
* @return The complete INNER JOIN SQL query as a string.
Expand Down
14 changes: 14 additions & 0 deletions query/src/main/java/com/blipblipcode/query/QueryDelete.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@ class QueryDelete private constructor(
return this
}

override fun getSqlOperators(): List<SQLOperator<*>> {
return operations.values.map {
it.operator
}
}

override fun getTableName(): String {
return table
}

override fun getSqlOperation(key: String): SQLOperator<*>? {
return operations[key]?.operator
}

/**
* Generates the SQL string for the DELETE statement.
* @return The complete DELETE SQL query as a string.
Expand Down
13 changes: 13 additions & 0 deletions query/src/main/java/com/blipblipcode/query/QueryInsert.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.blipblipcode.query

import com.blipblipcode.query.operator.Field
import com.blipblipcode.query.operator.SQLOperator

/**
* Represents a SQL INSERT statement.
Expand Down Expand Up @@ -58,6 +59,18 @@ class QueryInsert private constructor(
return this
}

override fun getSqlOperators(): List<SQLOperator<*>> {
return emptyList()
}

override fun getTableName(): String {
return table
}

override fun getSqlOperation(key: String): SQLOperator<*>? {
return null
}

/**
* Generates the SQL string for the INSERT statement.
* @return The complete INSERT SQL query as a string.
Expand Down
92 changes: 87 additions & 5 deletions query/src/main/java/com/blipblipcode/query/QuerySelect.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.blipblipcode.query

import com.blipblipcode.query.operator.Limit
import com.blipblipcode.query.operator.LogicalOperation
import com.blipblipcode.query.operator.LogicalType
import com.blipblipcode.query.operator.OrderBy
Expand All @@ -22,6 +23,7 @@ class QuerySelect private constructor(
private val fields: List<String>
) : Queryable {
private var orderBy: OrderBy? = null
private var limit: Limit? = null

companion object {
/**
Expand Down Expand Up @@ -79,7 +81,24 @@ class QuerySelect private constructor(
where = where,
operations = operations,
fields = fieldList
)
).apply {
this.orderBy = this@QuerySelect.orderBy
this.limit = this@QuerySelect.limit
}
}

override fun getSqlOperators(): List<SQLOperator<*>> {
return operations.values.map {
it.operator
}
}

override fun getTableName(): String {
return table
}

override fun getSqlOperation(key: String): SQLOperator<*>? {
return operations.get(key)?.operator
}

/**
Expand All @@ -92,24 +111,51 @@ class QuerySelect private constructor(
return buildString {
append("SELECT $fieldStr FROM $table WHERE ${where.toSQLString()} $operationsStr".trim())
if (orderBy != null) {
appendLine()
append(" ")
append(orderBy!!.asString())
}
if (limit != null) {
append(" ")
append(limit!!.asString())
}
}
}

/**
* Appends an ORDER BY clause to the entire UNION query.
* Note that in most SQL dialects, an ORDER BY clause can only be applied to the final result of a UNION, not to individual `SELECT` statements within it.
*
* @param columns A vararg of `OrderExpression` objects specifying the columns and direction for sorting.
* @param operator A vararg of `[OrderBy]` objects specifying the columns and direction for sorting.
* @return A new `QuerySelect` instance representing the UNION query with the added ORDER BY clause.
*/
fun orderBy(operator: OrderBy): Queryable {
orderBy = operator
return this
}

/**
* Adds a LIMIT clause to the query to limit the number of rows returned.
*
* @param count The maximum number of rows to return.
* @param offset The number of rows to skip before returning results (optional).
* @return The current `QuerySelect` instance for chaining.
*/
fun limit(count: Int, offset: Int? = null): QuerySelect {
limit = Limit(count, offset)
return this
}

/**
* Adds a LIMIT clause to the query using a Limit object.
*
* @param limitOperator The Limit object specifying the limit parameters.
* @return The current `QuerySelect` instance for chaining.
*/
fun limit(limitOperator: Limit): QuerySelect {
limit = limitOperator
return this
}


/**
* A builder for creating `QuerySelect` instances.
Expand All @@ -120,7 +166,9 @@ class QuerySelect private constructor(
private val operations: LinkedHashMap<String, LogicalOperation>
) {
private var where: SQLOperator<*>? = null
private var fields: List<String> = listOf("*" )
private var fields: List<String> = listOf("*")
private var orderBy: OrderBy? = null
private var limit: Limit? = null

/**
* Adds an AND condition to the WHERE clause.
Expand Down Expand Up @@ -234,6 +282,37 @@ class QuerySelect private constructor(
return this
}

/**
* Sets the ORDER BY clause for the query.
* @param orderBy The OrderBy object specifying the column and direction for sorting.
* @return The `QueryBuilder` instance for chaining.
*/
fun orderBy(orderBy: OrderBy): QueryBuilder {
this.orderBy = orderBy
return this
}

/**
* Sets a LIMIT clause for the query to limit the number of rows returned.
* @param count The maximum number of rows to return.
* @param offset The number of rows to skip before returning results (optional).
* @return The `QueryBuilder` instance for chaining.
*/
fun limit(count: Int, offset: Int? = null): QueryBuilder {
this.limit = Limit(count, offset)
return this
}

/**
* Sets a LIMIT clause for the query using a Limit object.
* @param limit The Limit object specifying the limit parameters.
* @return The `QueryBuilder` instance for chaining.
*/
fun limit(limit: Limit): QueryBuilder {
this.limit = limit
return this
}

/**
* Builds the `QuerySelect` instance.
* @return A new `QuerySelect` object.
Expand All @@ -246,7 +325,10 @@ class QuerySelect private constructor(
table = table,
operations = LinkedHashMap(operations),
fields = fields
)
).apply {
this@apply.orderBy = this@QueryBuilder.orderBy
this@apply.limit = this@QueryBuilder.limit
}
}
}
}
12 changes: 12 additions & 0 deletions query/src/main/java/com/blipblipcode/query/QueryUpdate.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,18 @@ class QueryUpdate private constructor(
return this
}

override fun getSqlOperators(): List<SQLOperator<*>> {
return emptyList()
}

override fun getTableName(): String {
return table
}

override fun getSqlOperation(key: String): SQLOperator<*>? {
return null
}

/**
* Generates the SQL string for the UPDATE statement.
* @return The complete UPDATE SQL query as a string.
Expand Down
23 changes: 23 additions & 0 deletions query/src/main/java/com/blipblipcode/query/Queryable.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,32 @@
package com.blipblipcode.query

import com.blipblipcode.query.operator.SQLOperator

/**
* Represents an object that can be converted to a SQL query string.
*/
interface Queryable {
/**
* Returns a list of all SQL operators used in the query.
* @return A list of [SQLOperator] instances.
*/
fun getSqlOperators(): List<SQLOperator<*>>
/**
* Returns the table name associated with the queryable object.
* This is typically derived from the class name of the implementing object.
* @return The table name as a string.
*/
fun getTableName(): String


/**
* Returns the corresponding SQL operation string for a given [SQLOperator].
*
* @param key The [SQLOperator] enum constant.
* @return The [SQLOperator] representation of the SQL operation or NULL if not exist.
*/
fun getSqlOperation(key: String): SQLOperator<*>?

/**
* Returns the SQL query string representation of the object.
* @return The SQL query string.
Expand Down
Loading