sql-blocks 0.31.89__py3-none-any.whl → 1.25__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sql_blocks/sql_blocks.py CHANGED
@@ -22,6 +22,7 @@ KEYWORD = {
22
22
 
23
23
  SELECT, FROM, WHERE, GROUP_BY, ORDER_BY, LIMIT = KEYWORD.keys()
24
24
  USUAL_KEYS = [SELECT, WHERE, GROUP_BY, ORDER_BY, LIMIT]
25
+ TO_LIST = lambda x: x if isinstance(x, list) else [x]
25
26
 
26
27
 
27
28
  class SQLObject:
@@ -110,9 +111,6 @@ class SQLObject:
110
111
  self.values[key] = result
111
112
 
112
113
 
113
- class Function:
114
- ...
115
-
116
114
  class Field:
117
115
  prefix = ''
118
116
 
@@ -134,17 +132,6 @@ class Field:
134
132
  )
135
133
 
136
134
 
137
- class Avg(Function, Field):
138
- ...
139
- class Min(Function, Field):
140
- ...
141
- class Max(Function, Field):
142
- ...
143
- class Sum(Function, Field):
144
- ...
145
- class Count(Function, Field):
146
- ...
147
-
148
135
  class Distinct(Field):
149
136
  prefix = 'DISTINCT '
150
137
 
@@ -163,6 +150,107 @@ class NamedField:
163
150
  )
164
151
 
165
152
 
153
+ class Function:
154
+ instance: dict = {}
155
+
156
+ def __init__(self, *params: list):
157
+ func_name = self.__class__.__name__
158
+ Function.instance[func_name] = self
159
+ self.params = [str(p) for p in params]
160
+ self.class_type = Field
161
+ self.pattern = '{}({})'
162
+ self.extra = {}
163
+
164
+ def As(self, field_alias: str, modifiers=None):
165
+ if modifiers:
166
+ for mod in TO_LIST(modifiers):
167
+ self.extra[field_alias] = mod
168
+ self.class_type = NamedField(field_alias)
169
+ return self
170
+
171
+ @classmethod
172
+ def format(cls, name: str, main: SQLObject) -> str:
173
+ obj = cls.get_instance()
174
+ params = [
175
+ Field.format(name, main)
176
+ ] + obj.params
177
+ return obj.pattern.format(
178
+ cls.__name__,
179
+ ', '.join(params)
180
+ )
181
+
182
+ def __add(self, name: str, main: SQLObject):
183
+ name = self.format(name, main)
184
+ self.class_type.add(name, main)
185
+ if self.extra:
186
+ main.__call__(**self.extra)
187
+
188
+ @classmethod
189
+ def get_instance(cls):
190
+ obj = Function.instance.get(cls.__name__)
191
+ if not obj:
192
+ obj = cls()
193
+ return obj
194
+
195
+ @classmethod
196
+ def add(cls, name: str, main: SQLObject):
197
+ cls.get_instance().__add(name, main)
198
+
199
+
200
+ # ---- String Functions: ---------------------------------
201
+ class SubString(Function):
202
+ ...
203
+
204
+ # ---- Numeric Functions: --------------------------------
205
+ class Round(Function):
206
+ ...
207
+
208
+ # --- Date Functions: ------------------------------------
209
+ class DateDiff(Function):
210
+ ...
211
+ class Extract(Function):
212
+ ...
213
+ class DatePart(Function):
214
+ ...
215
+ class Current_Date(Function):
216
+ ...
217
+
218
+ class Aggregate:
219
+ break_lines: bool = True
220
+
221
+ def over(self, **args):
222
+ keywords = ' '.join(
223
+ '{}{} BY {}'.format(
224
+ '\n\t\t' if self.break_lines else '',
225
+ key.upper(), args[key]
226
+ ) for key in ('partition', 'order')
227
+ if key in args
228
+ )
229
+ if keywords and self.break_lines:
230
+ keywords += '\n\t'
231
+ self.pattern = '{}({})' + f' OVER({keywords})'
232
+ return self
233
+
234
+
235
+ # ---- Aggregate Functions: -------------------------------
236
+ class Avg(Aggregate, Function):
237
+ ...
238
+ class Min(Aggregate, Function):
239
+ ...
240
+ class Max(Aggregate, Function):
241
+ ...
242
+ class Sum(Aggregate, Function):
243
+ ...
244
+ class Count(Aggregate, Function):
245
+ ...
246
+
247
+ # ---- Conversions and other Functions: ---------------------
248
+ class Coalesce(Function):
249
+ ...
250
+ class Cast(Function):
251
+ ...
252
+
253
+
166
254
  class ExpressionField:
167
255
  def __init__(self, expr: str):
168
256
  self.expr = expr
@@ -361,14 +449,9 @@ class Between:
361
449
  Where.lte(self.end).add(name, main)
362
450
 
363
451
 
364
- class SortType(Enum):
365
- ASC = ''
366
- DESC = ' DESC'
367
-
368
- class OrderBy:
369
- sort: SortType = SortType.ASC
452
+ class Clause:
370
453
  @classmethod
371
- def add(cls, name: str, main: SQLObject):
454
+ def format(cls, name: str, main: SQLObject) -> str:
372
455
  def is_function() -> bool:
373
456
  diff = main.diff(SELECT, [name.lower()], True)
374
457
  FUNCTION_CLASS = {f.__name__.lower(): f for f in Function.__subclasses__()}
@@ -378,13 +461,28 @@ class OrderBy:
378
461
  name = found[0].replace('_', '')
379
462
  elif main.alias and not is_function():
380
463
  name = f'{main.alias}.{name}'
464
+ return name
465
+
466
+
467
+ class SortType(Enum):
468
+ ASC = ''
469
+ DESC = ' DESC'
470
+
471
+
472
+ class OrderBy(Clause):
473
+ sort: SortType = SortType.ASC
474
+
475
+ @classmethod
476
+ def add(cls, name: str, main: SQLObject):
477
+ name = cls.format(name, main)
381
478
  main.values.setdefault(ORDER_BY, []).append(name+cls.sort.value)
382
479
 
383
480
 
384
- class GroupBy:
385
- @staticmethod
386
- def add(name: str, main: SQLObject):
387
- main.values.setdefault(GROUP_BY, []).append(f'{main.alias}.{name}')
481
+ class GroupBy(Clause):
482
+ @classmethod
483
+ def add(cls, name: str, main: SQLObject):
484
+ name = cls.format(name, main)
485
+ main.values.setdefault(GROUP_BY, []).append(name)
388
486
 
389
487
 
390
488
  class Having:
@@ -1095,9 +1193,8 @@ class Select(SQLObject):
1095
1193
  return self.translate_to(QueryLanguage)
1096
1194
 
1097
1195
  def __call__(self, **values):
1098
- to_list = lambda x: x if isinstance(x, list) else [x]
1099
1196
  for name, params in values.items():
1100
- for obj in to_list(params):
1197
+ for obj in TO_LIST(params):
1101
1198
  obj.add(name, self)
1102
1199
  return self
1103
1200
 
@@ -1260,22 +1357,3 @@ def detect(text: str) -> Select:
1260
1357
  for query in query_list[1:]:
1261
1358
  result += query
1262
1359
  return result
1263
-
1264
-
1265
- if __name__ == "__main__":
1266
- print('░▒▓▒░'*20)
1267
- p, c, a = Select.parse(
1268
- '''
1269
- Professor(?nome="Júlio Cascalles", id)
1270
- <- Curso@disciplina(professor, aluno) ->
1271
- Aluno(id ^count$qtd_alunos)
1272
- ''', CypherParser
1273
- )
1274
- print(p)
1275
- print('-'*50)
1276
- print(c)
1277
- print('-'*50)
1278
- print(a)
1279
- print('='*50)
1280
- print(a + c + p)
1281
- print('░▒▓▒░'*20)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sql_blocks
3
- Version: 0.31.89
3
+ Version: 1.25
4
4
  Summary: Allows you to create objects for parts of SQL query commands. Also to combine these objects by joining them, adding or removing parts...
5
5
  Home-page: https://github.com/julio-cascalles/sql_blocks
6
6
  Author: Júlio Cascalles
@@ -427,7 +427,7 @@ ORDER BY
427
427
  It is useful to write a query in a few lines, without specifying the script type (cypher, mongoDB, SQL, Neo4J...)
428
428
  ### Examples:
429
429
 
430
- > **1 - Relationship**
430
+ > **13.1 - Relationship**
431
431
  ```
432
432
  query = detect(
433
433
  'MATCH(c:Customer)<-[:Order]->(p:Product)RETURN c, p'
@@ -439,7 +439,7 @@ print(query)
439
439
  Order ord
440
440
  LEFT JOIN Customer cus ON (ord.customer_id = cus.id)
441
441
  RIGHT JOIN Product pro ON (ord.product_id = pro.id)
442
- > **2 - Grouping**
442
+ > **13.2 - Grouping**
443
443
  ```
444
444
  query = detect(
445
445
  'People@gender(avg$age?region="SOUTH"^count$qtde)'
@@ -460,7 +460,7 @@ print(query)
460
460
  ORDER BY
461
461
  peo.qtde
462
462
 
463
- > **3 - Many conditions...**
463
+ > **13.3 - Many conditions...**
464
464
  ```
465
465
  print( detect('''
466
466
  db.people.find({
@@ -491,7 +491,7 @@ print(query)
491
491
  ORDER BY
492
492
  peo.user_id DESC
493
493
 
494
- > **4 - Relations with same table twice (or more)**
494
+ > **13.4 - Relations with same table twice (or more)**
495
495
 
496
496
  Automatically assigns aliases to each side of the relationship (In this example, one user invites another to add to their contact list)
497
497
  ```
@@ -516,3 +516,54 @@ It consists of the inverse process of parsing: From a Select object, it returns
516
516
  * QueryLanguage - default
517
517
  * MongoDBLanguage
518
518
  * Neo4JLanguage
519
+
520
+ ---
521
+ ### 14 - Window Function
522
+
523
+ Aggregation functions (Avg, Min, Max, Sum, Count) have the **over** method...
524
+
525
+ query=Select(
526
+ 'Enrollment e',
527
+ payment=Sum().over(
528
+ partition='student_id', order='due_date'
529
+ ).As('sum_per_student')
530
+ )
531
+
532
+ ...that generates the following query:
533
+
534
+ ```
535
+ SELECT
536
+ Sum(e.payment) OVER(
537
+ PARTITION BY student_id
538
+ ORDER BY due_date
539
+ ) as sum_per_student
540
+ FROM
541
+ Enrollment e
542
+ ```
543
+ ---
544
+ ### 15 - The `As` method:
545
+ query=Select(
546
+ 'Customers c',
547
+ phone=[
548
+ Not.is_null(),
549
+ SubString(1, 4).As('area_code', GroupBy)
550
+ ],
551
+ customer_id=[
552
+ Count().As('customer_count', OrderBy),
553
+ Having.count(gt(5))
554
+ ]
555
+ )
556
+ You can use the result of a function as a new field -- and optionally use it in ORDER BY and/or GROUP BY clause(s):
557
+ ```
558
+ SELECT
559
+ SubString(c.phone, 1, 4) as area_code,
560
+ Count(c.customer_id) as customer_count
561
+ FROM
562
+ Customers c
563
+ WHERE
564
+ NOT c.phone IS NULL
565
+ GROUP BY
566
+ area_code HAVING Count(c.customer_id) > 5
567
+ ORDER BY
568
+ customer_count
569
+ ```
@@ -0,0 +1,7 @@
1
+ sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
2
+ sql_blocks/sql_blocks.py,sha256=QxopGbzRtBgG_9oAs1ovBATFplDqrzEFSLwyKbOL-W8,45499
3
+ sql_blocks-1.25.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
+ sql_blocks-1.25.dist-info/METADATA,sha256=cvHewfK05stZRHfWZeyIMMtKRjdOGxZN38o94JkVS-U,13421
5
+ sql_blocks-1.25.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
+ sql_blocks-1.25.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
+ sql_blocks-1.25.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
2
- sql_blocks/sql_blocks.py,sha256=nsIT8JEeYHw3KIkzAUHUdzUAR_i2asJmdytsvW0hYKc,43342
3
- sql_blocks-0.31.89.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
- sql_blocks-0.31.89.dist-info/METADATA,sha256=xKHVfM76nzvZBr-TYC5_PN4bAvYW9oWoi5ChPIPdbDE,12202
5
- sql_blocks-0.31.89.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
- sql_blocks-0.31.89.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
- sql_blocks-0.31.89.dist-info/RECORD,,