Skip to content

Commit 3f505cc

Browse files
committed
HAVING and NOW() 🍡
1 parent 9357a9c commit 3f505cc

File tree

23 files changed

+356
-113
lines changed

23 files changed

+356
-113
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## 0.3.0 : 2020-05-20
4+
5+
- **Feature**: `HAVING` support
6+
- **Feature**: `NOW()` support
7+
- **Fix**: `Comparision` allows to have every `BaseType` as `properties`
8+
- **Fix**: Interval value is quoted now
9+
310
## 0.2.2 : 2020-04-16
411

512
- **Change**: Ability to pass `structures.Distinct` into `functions.StringAgg`

docs/functions/now.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Now
2+
3+
## Basic information
4+
5+
| | |
6+
|-----------------|--------------------------------|
7+
| **Object type** | `functions.Now` |
8+
| **Since** | 0.3.0 |
9+
| **Dialects** | `MySQL` `MariaDB` `PostgreSQL` |
10+
11+
## Object attributes
12+
13+
| Attribute | Accepts | Required |
14+
|-----------------|----------------------------------------------------------|----------|
15+
| obj | `functions.Now` | True |
16+
| alias | String | False |
17+
18+
## JSON format
19+
20+
```json
21+
{
22+
"obj": "functions.Now",
23+
"alias": "today"
24+
}
25+
```
26+
27+
## SQL
28+
29+
```sql
30+
NOW() AS today
31+
```

docs/structures/interval.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@
2929
## SQL
3030

3131
```sql
32-
INTERVAL -5 DAY
32+
INTERVAL '-5 DAY'
3333
```
3434

docs/structures/query.md

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616
| entity | String | True |
1717
| properties | List[`functions.*` `properties.Property` `structures.Distinct` `structures.CastOperator`] | True |
1818
| joins | List[`structures.Join`] | False |
19-
| conditions | `structures.Operator` | False |
19+
| conditions | `structures.Operator` `structures.Comparision` | False |
2020
| order | List[`structures.Order`] | False |
2121
| group | List[`functions.*` `properties.Property`] | False |
22+
| having | `structures.Operator` `structures.Comparision` | False |
2223
| limit | `structures.Limit` | False |
2324
| alias | String | False |
2425

@@ -31,13 +32,15 @@
3132
"properties": [
3233
{
3334
"obj": "properties.Property",
34-
"name": "users.name"
35+
"name": "users.name",
36+
"alias": "users_name"
3537
},
3638
{
3739
"obj": "functions.ConvertTimezone",
3840
"property": {
3941
"obj": "properties.Property",
40-
"name": "users.created_at"
42+
"name": "users.created_at",
43+
"alias": null
4144
},
4245
"date_from": {
4346
"obj": "properties.Constant",
@@ -46,7 +49,8 @@
4649
"date_to": {
4750
"obj": "properties.Constant",
4851
"value": "Europe/Bratislava"
49-
}
52+
},
53+
"alias": "valid_timezone"
5054
}
5155
],
5256
"joins": [
@@ -63,11 +67,13 @@
6367
"properties": [
6468
{
6569
"obj": "properties.Property",
66-
"name": "transactions.user_id"
70+
"name": "transactions.user_id",
71+
"alias": null
6772
},
6873
{
6974
"obj": "properties.Property",
70-
"name": "users.id"
75+
"name": "users.id",
76+
"alias": null
7177
}
7278
],
7379
"operation": "eq"
@@ -77,17 +83,21 @@
7783
"properties": [
7884
{
7985
"obj": "properties.Property",
80-
"name": "transactions.creator_id"
86+
"name": "transactions.creator_id",
87+
"alias": null
8188
},
8289
{
8390
"obj": "properties.Property",
84-
"name": "users.id"
91+
"name": "users.id",
92+
"alias": null
8593
}
8694
],
8795
"operation": "neq"
8896
}
89-
]
90-
}
97+
],
98+
"alias": null
99+
},
100+
"alias": null
91101
}
92102
],
93103
"conditions": {
@@ -99,7 +109,8 @@
99109
"properties": [
100110
{
101111
"obj": "properties.Property",
102-
"name": "users.age"
112+
"name": "users.age",
113+
"alias": null
103114
},
104115
{
105116
"obj": "properties.Constant",
@@ -113,7 +124,8 @@
113124
"properties": [
114125
{
115126
"obj": "properties.Property",
116-
"name": "users.city"
127+
"name": "users.city",
128+
"alias": null
117129
},
118130
{
119131
"obj": "properties.Array",
@@ -131,34 +143,58 @@
131143
],
132144
"operation": "in"
133145
}
134-
]
146+
],
147+
"alias": null
148+
},
149+
"having": {
150+
"obj": "structures.Comparision",
151+
"properties": [
152+
{
153+
"obj": "functions.Sum",
154+
"property": {
155+
"obj": "properties.Property",
156+
"name": "transactions.value",
157+
"alias": null
158+
},
159+
"alias": null
160+
},
161+
{
162+
"obj": "properties.Constant",
163+
"value": "420"
164+
}
165+
],
166+
"operation": "gt"
135167
},
136168
"order": [
137169
{
138170
"obj": "structures.Order",
139171
"property": {
140172
"obj": "properties.Property",
141-
"name": "users.surname"
173+
"name": "users.surname",
174+
"alias": null
142175
},
143176
"kind": "ASC"
144177
},
145178
{
146179
"obj": "structures.Order",
147180
"property": {
148181
"obj": "properties.Property",
149-
"name": "users.name"
182+
"name": "users.name",
183+
"alias": null
150184
},
151185
"kind": "DESC"
152186
}
153187
],
154188
"group": [
155189
{
156190
"obj": "properties.Property",
157-
"name": "users.email"
191+
"name": "users.email",
192+
"alias": null
158193
},
159194
{
160195
"obj": "properties.Property",
161-
"name": "users.id"
196+
"name": "users.id",
197+
"alias": null
162198
}
163199
],
164200
"limit": {
@@ -187,12 +223,10 @@
187223
(users.age >= 15)
188224
AND (users.city IN ('Martin', 'Bratislava'))
189225
)
190-
GROUP BY users.email,
191-
users.id
192-
ORDER BY users.surname ASC,
193-
users.name DESC
226+
GROUP BY users.email, users.id
227+
HAVING (SUM(transactions.value) > 420)
228+
ORDER BY users.surname ASC, users.name DESC
194229
LIMIT 10 OFFSET 4
195230
)
196231
AS my_query
197232
```
198-

duckql/functions/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from .sum import Sum
1313
from .weekday import Weekday
1414
from .string_agg import StringAgg
15+
from .now import Now
1516

1617
__all__ = [
1718
"Avg",
@@ -28,5 +29,6 @@
2829
"Min",
2930
"Sum",
3031
"Weekday",
31-
"StringAgg"
32+
"StringAgg",
33+
"Now"
3234
]

duckql/functions/now.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from typing_extensions import Literal
2+
3+
from .base import BaseFunction
4+
5+
6+
class Now(BaseFunction):
7+
obj: Literal['functions.Avg'] = 'functions.Now'
8+
alias: str = None
9+
10+
def to_sql(self) -> str:
11+
sql = "NOW()"
12+
13+
if self.alias is not None:
14+
sql = f"{sql} AS {self.alias}"
15+
16+
return sql

duckql/functions/tests/test_date_add.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ def test_simple():
1010
alias="add_dated"
1111
)
1212

13-
assert str(my_function) == "DATE_ADD(users.created_at, INTERVAL 4 YEAR_MONTH) AS add_dated"
13+
assert str(my_function) == "DATE_ADD(users.created_at, INTERVAL '4 YEAR_MONTH') AS add_dated"

duckql/functions/tests/test_date_sub.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ def test_simple():
1010
alias="sub_dated"
1111
)
1212

13-
assert str(my_function) == "DATE_SUB(users.created_at, INTERVAL 5 DAY_MINUTE) AS sub_dated"
13+
assert str(my_function) == "DATE_SUB(users.created_at, INTERVAL '5 DAY_MINUTE') AS sub_dated"

duckql/functions/tests/test_now.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from ..now import Now
2+
3+
4+
def test_property():
5+
my_now = Now()
6+
7+
assert str(my_now) == 'NOW()'
8+
9+
10+
def test_alias():
11+
my_now = Now(alias='"now_name')
12+
13+
assert str(my_now) == 'NOW() AS now_name'

duckql/structures/comparision.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
from enum import Enum
2-
from typing import Union, List
2+
from typing import List
33

4-
from duckql.functions.base import BaseFunction
54
from pydantic import validator
65
from typing_extensions import Literal
76

87
from duckql.exceptions import ParseError
98
from duckql.base import BaseType
10-
from duckql.properties.constant import Constant
11-
from duckql.properties.property import Property
129
from duckql.properties.array import Array
13-
from duckql.properties.boolean import Boolean
14-
from duckql.properties.null import Null
1510

1611

1712
class Comparision(BaseType):
@@ -57,7 +52,7 @@ def containers(cls) -> List["Comparision.Operation"]:
5752
return [cls.NOT_IN, cls.IN]
5853

5954
obj: Literal['structures.Comparision'] = 'structures.Comparision'
60-
properties: List[Union[Constant, Property, BaseFunction, Array, Boolean, Null]]
55+
properties: List[BaseType]
6156
operation: Operation
6257

6358
@validator('properties', pre=True)

0 commit comments

Comments
 (0)