Skip to content

Commit e9765c7

Browse files
authored
Merge pull request #1 from LeandroLCD/develop
Develop
2 parents 1a80b82 + 9318f21 commit e9765c7

File tree

15 files changed

+505
-27
lines changed

15 files changed

+505
-27
lines changed

LIMIT_EXAMPLE.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Implementación del Operador LIMIT
2+
3+
## Descripción
4+
5+
Se ha implementado exitosamente el operador LIMIT para la clase QuerySelect, permitiendo limitar el número de filas devueltas en una consulta SELECT.
6+
7+
## Características implementadas
8+
9+
1. **Clase Limit**: Se creó una nueva clase `Limit` en el paquete `operator` que maneja los parámetros de límite y offset.
10+
11+
2. **Soporte en QuerySelect**: Se agregó soporte completo para LIMIT en la clase QuerySelect y su QueryBuilder.
12+
13+
3. **Métodos disponibles**:
14+
- `limit(count: Int)`: Limita el número de filas a devolver
15+
- `limit(count: Int, offset: Int?)`: Limita el número de filas con un offset opcional
16+
- `limit(limitOperator: Limit)`: Acepta un objeto Limit directamente
17+
18+
## Ejemplos de uso
19+
20+
### Uso básico con Builder
21+
```kotlin
22+
val query = QuerySelect.builder("users")
23+
.where(SQLOperator.Equals("status", "active"))
24+
.limit(10)
25+
.build()
26+
27+
// Genera: SELECT * FROM users WHERE status = 'active' LIMIT 10
28+
```
29+
30+
### Uso con offset
31+
```kotlin
32+
val query = QuerySelect.builder("users")
33+
.where(SQLOperator.Equals("status", "active"))
34+
.limit(10, 5)
35+
.build()
36+
37+
// Genera: SELECT * FROM users WHERE status = 'active' LIMIT 10 OFFSET 5
38+
```
39+
40+
### Uso con objeto Limit
41+
```kotlin
42+
val limitOperator = Limit(count = 10, offset = 5)
43+
val query = QuerySelect.builder("users")
44+
.where(SQLOperator.Equals("status", "active"))
45+
.limit(limitOperator)
46+
.build()
47+
48+
// Genera: SELECT * FROM users WHERE status = 'active' LIMIT 10 OFFSET 5
49+
```
50+
51+
### Encadenamiento de métodos
52+
```kotlin
53+
val query = QuerySelect.builder("users")
54+
.where(SQLOperator.Equals("status", "active"))
55+
.and("age", SQLOperator.GreaterThan("age", 18))
56+
.orderBy(OrderBy.Desc("created_at"))
57+
.limit(20)
58+
.build()
59+
60+
// Genera: SELECT * FROM users WHERE status = 'active' AND age > 18
61+
// ORDER BY created_at DESC
62+
// LIMIT 20
63+
```
64+
65+
### Modificación de límite en consulta existente
66+
```kotlin
67+
val query = QuerySelect.builder("users")
68+
.where(SQLOperator.Equals("status", "active"))
69+
.build()
70+
71+
// Agregar límite después de crear la consulta
72+
query.limit(15, 10)
73+
74+
// Genera: SELECT * FROM users WHERE status = 'active' LIMIT 15 OFFSET 10
75+
```
76+
77+
## Validaciones implementadas
78+
79+
La clase Limit incluye validaciones para garantizar que:
80+
- El count debe ser no negativo
81+
- El offset (si se proporciona) debe ser no negativo
82+
83+
## Orden de ejecución SQL
84+
85+
La implementación respeta el orden estándar de SQL:
86+
1. SELECT campos
87+
2. FROM tabla
88+
3. WHERE condiciones
89+
4. ORDER BY (si existe)
90+
5. LIMIT (si existe)
91+
92+
Esta implementación permite crear consultas SQL complejas con paginación de manera fluida y manteniendo la consistencia con el resto del framework.

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ Diseñada para integrarse perfectamente con la base de datos de Android y Room a
3636
- [🔗 Integración con Room](#-integración-con-room)
3737
- [📝 Ejemplos Avanzados](#-ejemplos-avanzados)
3838
- [🤝 Contribuir](#-contribuir)
39-
- [📄 Licencia](#-licencia)
4039

4140
---
4241

@@ -92,6 +91,10 @@ val selectQuery = QuerySelect.builder("users")
9291
.and("status", SQLOperator.Equals("status", "active"))
9392
.setFields("name", "email")
9493
.build()
94+
// Agrega un límite de 10 resultados
95+
selectQuery.limit(10)
96+
// Agrega un offset
97+
selectQuery.limit(10, 5)
9598

9699
val sqlString = selectQuery.asSql()
97100
```

gradlew

100644100755
File mode changed.

query/src/main/java/com/blipblipcode/query/InnerJoint.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.blipblipcode.query
22

33
import com.blipblipcode.query.operator.OrderBy
4+
import com.blipblipcode.query.operator.SQLOperator
45

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

1819
private var orderBy: OrderBy? = null
1920

21+
override fun getSqlOperators(): List<SQLOperator<*>> {
22+
return queries.flatMap { it.getSqlOperators() }
23+
}
24+
25+
override fun getTableName(): String {
26+
return queries.joinToString(", ") { it.getTableName() }
27+
}
28+
29+
override fun getSqlOperation(key: String): SQLOperator<*>? {
30+
return queries.flatMap { it.getSqlOperators() }.firstOrNull { it.column.equals(key, ignoreCase = true) }
31+
}
32+
2033
/**
2134
* Generates the SQL string for the INNER JOIN statement.
2235
* @return The complete INNER JOIN SQL query as a string.

query/src/main/java/com/blipblipcode/query/QueryDelete.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,20 @@ class QueryDelete private constructor(
6363
return this
6464
}
6565

66+
override fun getSqlOperators(): List<SQLOperator<*>> {
67+
return operations.values.map {
68+
it.operator
69+
}
70+
}
71+
72+
override fun getTableName(): String {
73+
return table
74+
}
75+
76+
override fun getSqlOperation(key: String): SQLOperator<*>? {
77+
return operations[key]?.operator
78+
}
79+
6680
/**
6781
* Generates the SQL string for the DELETE statement.
6882
* @return The complete DELETE SQL query as a string.

query/src/main/java/com/blipblipcode/query/QueryInsert.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.blipblipcode.query
22

33
import com.blipblipcode.query.operator.Field
4+
import com.blipblipcode.query.operator.SQLOperator
45

56
/**
67
* Represents a SQL INSERT statement.
@@ -58,6 +59,18 @@ class QueryInsert private constructor(
5859
return this
5960
}
6061

62+
override fun getSqlOperators(): List<SQLOperator<*>> {
63+
return emptyList()
64+
}
65+
66+
override fun getTableName(): String {
67+
return table
68+
}
69+
70+
override fun getSqlOperation(key: String): SQLOperator<*>? {
71+
return null
72+
}
73+
6174
/**
6275
* Generates the SQL string for the INSERT statement.
6376
* @return The complete INSERT SQL query as a string.

query/src/main/java/com/blipblipcode/query/QuerySelect.kt

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.blipblipcode.query
22

3+
import com.blipblipcode.query.operator.Limit
34
import com.blipblipcode.query.operator.LogicalOperation
45
import com.blipblipcode.query.operator.LogicalType
56
import com.blipblipcode.query.operator.OrderBy
@@ -22,6 +23,7 @@ class QuerySelect private constructor(
2223
private val fields: List<String>
2324
) : Queryable {
2425
private var orderBy: OrderBy? = null
26+
private var limit: Limit? = null
2527

2628
companion object {
2729
/**
@@ -79,7 +81,24 @@ class QuerySelect private constructor(
7981
where = where,
8082
operations = operations,
8183
fields = fieldList
82-
)
84+
).apply {
85+
this.orderBy = this@QuerySelect.orderBy
86+
this.limit = this@QuerySelect.limit
87+
}
88+
}
89+
90+
override fun getSqlOperators(): List<SQLOperator<*>> {
91+
return operations.values.map {
92+
it.operator
93+
}
94+
}
95+
96+
override fun getTableName(): String {
97+
return table
98+
}
99+
100+
override fun getSqlOperation(key: String): SQLOperator<*>? {
101+
return operations.get(key)?.operator
83102
}
84103

85104
/**
@@ -92,24 +111,51 @@ class QuerySelect private constructor(
92111
return buildString {
93112
append("SELECT $fieldStr FROM $table WHERE ${where.toSQLString()} $operationsStr".trim())
94113
if (orderBy != null) {
95-
appendLine()
114+
append(" ")
96115
append(orderBy!!.asString())
97116
}
117+
if (limit != null) {
118+
append(" ")
119+
append(limit!!.asString())
120+
}
98121
}
99122
}
100123

101124
/**
102125
* Appends an ORDER BY clause to the entire UNION query.
103126
* 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.
104127
*
105-
* @param columns A vararg of `OrderExpression` objects specifying the columns and direction for sorting.
128+
* @param operator A vararg of `[OrderBy]` objects specifying the columns and direction for sorting.
106129
* @return A new `QuerySelect` instance representing the UNION query with the added ORDER BY clause.
107130
*/
108131
fun orderBy(operator: OrderBy): Queryable {
109132
orderBy = operator
110133
return this
111134
}
112135

136+
/**
137+
* Adds a LIMIT clause to the query to limit the number of rows returned.
138+
*
139+
* @param count The maximum number of rows to return.
140+
* @param offset The number of rows to skip before returning results (optional).
141+
* @return The current `QuerySelect` instance for chaining.
142+
*/
143+
fun limit(count: Int, offset: Int? = null): QuerySelect {
144+
limit = Limit(count, offset)
145+
return this
146+
}
147+
148+
/**
149+
* Adds a LIMIT clause to the query using a Limit object.
150+
*
151+
* @param limitOperator The Limit object specifying the limit parameters.
152+
* @return The current `QuerySelect` instance for chaining.
153+
*/
154+
fun limit(limitOperator: Limit): QuerySelect {
155+
limit = limitOperator
156+
return this
157+
}
158+
113159

114160
/**
115161
* A builder for creating `QuerySelect` instances.
@@ -120,7 +166,9 @@ class QuerySelect private constructor(
120166
private val operations: LinkedHashMap<String, LogicalOperation>
121167
) {
122168
private var where: SQLOperator<*>? = null
123-
private var fields: List<String> = listOf("*" )
169+
private var fields: List<String> = listOf("*")
170+
private var orderBy: OrderBy? = null
171+
private var limit: Limit? = null
124172

125173
/**
126174
* Adds an AND condition to the WHERE clause.
@@ -234,6 +282,37 @@ class QuerySelect private constructor(
234282
return this
235283
}
236284

285+
/**
286+
* Sets the ORDER BY clause for the query.
287+
* @param orderBy The OrderBy object specifying the column and direction for sorting.
288+
* @return The `QueryBuilder` instance for chaining.
289+
*/
290+
fun orderBy(orderBy: OrderBy): QueryBuilder {
291+
this.orderBy = orderBy
292+
return this
293+
}
294+
295+
/**
296+
* Sets a LIMIT clause for the query to limit the number of rows returned.
297+
* @param count The maximum number of rows to return.
298+
* @param offset The number of rows to skip before returning results (optional).
299+
* @return The `QueryBuilder` instance for chaining.
300+
*/
301+
fun limit(count: Int, offset: Int? = null): QueryBuilder {
302+
this.limit = Limit(count, offset)
303+
return this
304+
}
305+
306+
/**
307+
* Sets a LIMIT clause for the query using a Limit object.
308+
* @param limit The Limit object specifying the limit parameters.
309+
* @return The `QueryBuilder` instance for chaining.
310+
*/
311+
fun limit(limit: Limit): QueryBuilder {
312+
this.limit = limit
313+
return this
314+
}
315+
237316
/**
238317
* Builds the `QuerySelect` instance.
239318
* @return A new `QuerySelect` object.
@@ -246,7 +325,10 @@ class QuerySelect private constructor(
246325
table = table,
247326
operations = LinkedHashMap(operations),
248327
fields = fields
249-
)
328+
).apply {
329+
this@apply.orderBy = this@QueryBuilder.orderBy
330+
this@apply.limit = this@QueryBuilder.limit
331+
}
250332
}
251333
}
252334
}

query/src/main/java/com/blipblipcode/query/QueryUpdate.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,18 @@ class QueryUpdate private constructor(
7474
return this
7575
}
7676

77+
override fun getSqlOperators(): List<SQLOperator<*>> {
78+
return emptyList()
79+
}
80+
81+
override fun getTableName(): String {
82+
return table
83+
}
84+
85+
override fun getSqlOperation(key: String): SQLOperator<*>? {
86+
return null
87+
}
88+
7789
/**
7890
* Generates the SQL string for the UPDATE statement.
7991
* @return The complete UPDATE SQL query as a string.

query/src/main/java/com/blipblipcode/query/Queryable.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,32 @@
11
package com.blipblipcode.query
22

3+
import com.blipblipcode.query.operator.SQLOperator
4+
35
/**
46
* Represents an object that can be converted to a SQL query string.
57
*/
68
interface Queryable {
9+
/**
10+
* Returns a list of all SQL operators used in the query.
11+
* @return A list of [SQLOperator] instances.
12+
*/
13+
fun getSqlOperators(): List<SQLOperator<*>>
14+
/**
15+
* Returns the table name associated with the queryable object.
16+
* This is typically derived from the class name of the implementing object.
17+
* @return The table name as a string.
18+
*/
19+
fun getTableName(): String
20+
21+
22+
/**
23+
* Returns the corresponding SQL operation string for a given [SQLOperator].
24+
*
25+
* @param key The [SQLOperator] enum constant.
26+
* @return The [SQLOperator] representation of the SQL operation or NULL if not exist.
27+
*/
28+
fun getSqlOperation(key: String): SQLOperator<*>?
29+
730
/**
831
* Returns the SQL query string representation of the object.
932
* @return The SQL query string.

0 commit comments

Comments
 (0)