sql-blocks 1.25.113__py3-none-any.whl → 1.25.1801__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
@@ -121,7 +121,8 @@ class SQLObject:
121
121
 
122
122
  SQL_CONST_SYSDATE = 'SYSDATE'
123
123
  SQL_CONST_CURR_DATE = 'Current_date'
124
- SQL_CONSTS = [SQL_CONST_SYSDATE, SQL_CONST_CURR_DATE]
124
+ SQL_ROW_NUM = 'ROWNUM'
125
+ SQL_CONSTS = [SQL_CONST_SYSDATE, SQL_CONST_CURR_DATE, SQL_ROW_NUM]
125
126
 
126
127
 
127
128
  class Field:
@@ -282,14 +283,15 @@ class Frame:
282
283
  keywords = ''
283
284
  for field, obj in args.items():
284
285
  is_valid = any([
285
- obj is class_type # or isinstance(obj, class_type)
286
- for class_type in (OrderBy, Partition)
286
+ obj is OrderBy,
287
+ obj is Partition,
288
+ isinstance(obj, Rows),
287
289
  ])
288
290
  if not is_valid:
289
291
  continue
290
292
  keywords += '{}{} {}'.format(
291
293
  '\n\t\t' if self.break_lines else ' ',
292
- obj.cls_to_str(), field
294
+ obj.cls_to_str(), field if field != '_' else ''
293
295
  )
294
296
  if keywords and self.break_lines:
295
297
  keywords += '\n\t'
@@ -561,6 +563,34 @@ class SortType(Enum):
561
563
  ASC = ''
562
564
  DESC = ' DESC'
563
565
 
566
+ class Row:
567
+ def __init__(self, value: int=0):
568
+ self.value = value
569
+
570
+ def __str__(self) -> str:
571
+ return '{} {}'.format(
572
+ 'UNBOUNDED' if self.value == 0 else self.value,
573
+ self.__class__.__name__.upper()
574
+ )
575
+
576
+ class Preceding(Row):
577
+ ...
578
+ class Following(Row):
579
+ ...
580
+ class Current(Row):
581
+ def __str__(self) -> str:
582
+ return 'CURRENT ROW'
583
+
584
+ class Rows:
585
+ def __init__(self, *rows: list[Row]):
586
+ self.rows = rows
587
+
588
+ def cls_to_str(self) -> str:
589
+ return 'ROWS {}{}'.format(
590
+ 'BETWEEN ' if len(self.rows) > 1 else '',
591
+ ' AND '.join(str(row) for row in self.rows)
592
+ )
593
+
564
594
 
565
595
  class OrderBy(Clause):
566
596
  sort: SortType = SortType.ASC
@@ -625,7 +655,7 @@ class Rule:
625
655
  ...
626
656
 
627
657
  class QueryLanguage:
628
- pattern = '{select}{_from}{where}{group_by}{order_by}'
658
+ pattern = '{select}{_from}{where}{group_by}{order_by}{limit}'
629
659
  has_default = {key: bool(key == SELECT) for key in KEYWORD}
630
660
 
631
661
  @staticmethod
@@ -653,13 +683,16 @@ class QueryLanguage:
653
683
  def set_group(self, values: list) -> str:
654
684
  return self.join_with_tabs(values, ',')
655
685
 
686
+ def set_limit(self, values: list) -> str:
687
+ return self.join_with_tabs(values, ' ')
688
+
656
689
  def __init__(self, target: 'Select'):
657
- self.KEYWORDS = [SELECT, FROM, WHERE, GROUP_BY, ORDER_BY]
690
+ self.KEYWORDS = [SELECT, FROM, WHERE, GROUP_BY, ORDER_BY, LIMIT]
658
691
  self.TABULATION = '\n\t' if target.break_lines else ' '
659
692
  self.LINE_BREAK = '\n' if target.break_lines else ' '
660
693
  self.TOKEN_METHODS = {
661
694
  SELECT: self.add_field, FROM: self.get_tables,
662
- WHERE: self.extract_conditions,
695
+ WHERE: self.extract_conditions, LIMIT: self.set_limit,
663
696
  ORDER_BY: self.sort_by, GROUP_BY: self.set_group,
664
697
  }
665
698
  self.result = {}
@@ -1308,10 +1341,21 @@ class Select(SQLObject):
1308
1341
  return True
1309
1342
 
1310
1343
  def limit(self, row_count: int=100, offset: int=0):
1311
- result = [str(row_count)]
1312
- if offset > 0:
1313
- result.append(f'OFFSET {offset}')
1314
- self.values.setdefault(LIMIT, result)
1344
+ if Function.dialect == Dialect.SQL_SERVER:
1345
+ fields = self.values.get(SELECT)
1346
+ if fields:
1347
+ fields[0] = f'SELECT TOP({row_count}) {fields[0]}'
1348
+ else:
1349
+ self.values[SELECT] = [f'SELECT TOP({row_count}) *']
1350
+ return self
1351
+ if Function.dialect == Dialect.ORACLE:
1352
+ Where.gte(row_count).add(SQL_ROW_NUM, self)
1353
+ if offset > 0:
1354
+ Where.lte(row_count+offset).add(SQL_ROW_NUM, self)
1355
+ return self
1356
+ self.values[LIMIT] = ['{}{}'.format(
1357
+ row_count, f' OFFSET {offset}' if offset > 0 else ''
1358
+ )]
1315
1359
  return self
1316
1360
 
1317
1361
  def match(self, field: str, key: str) -> bool:
@@ -1475,7 +1519,7 @@ def parser_class(text: str) -> Parser:
1475
1519
  return None
1476
1520
 
1477
1521
 
1478
- def detect(text: str) -> Select:
1522
+ def detect(text: str, join_queries: bool = True) -> Select:
1479
1523
  from collections import Counter
1480
1524
  parser = parser_class(text)
1481
1525
  if not parser:
@@ -1491,6 +1535,8 @@ def detect(text: str) -> Select:
1491
1535
  text = text[:begin] + new_name + '(' + text[end:]
1492
1536
  count -= 1
1493
1537
  query_list = Select.parse(text, parser)
1538
+ if not join_queries:
1539
+ return query_list
1494
1540
  result = query_list[0]
1495
1541
  for query in query_list[1:]:
1496
1542
  result += query
@@ -1498,15 +1544,14 @@ def detect(text: str) -> Select:
1498
1544
 
1499
1545
 
1500
1546
  if __name__ == '__main__':
1501
- p, c, a = Select.parse('''
1502
- Professor(?nome="Júlio Cascalles", id)
1503
- <- Curso@disciplina(professor, aluno) ->
1504
- Aluno(id ^count$qtd_alunos)
1505
- ''', CypherParser)
1506
- query = p + c + a
1507
- print('#######################################')
1508
- print(query)
1509
- print('***************************************')
1510
- query.optimize([RuleReplaceJoinBySubselect])
1511
- print(query)
1512
- print('#######################################')
1547
+ for dialect in Dialect:
1548
+ Function.dialect = dialect
1549
+ print(f'--------------{dialect.name}--------------')
1550
+ query = Select(
1551
+ 'Installments',
1552
+ _=DateDiff(
1553
+ Current_Date(),
1554
+ 'due_date'
1555
+ ).As('elapsed_time')
1556
+ ).limit(10)
1557
+ print(query)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sql_blocks
3
- Version: 1.25.113
3
+ Version: 1.25.1801
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
@@ -554,12 +554,18 @@ It consists of the inverse process of parsing: From a Select object, it returns
554
554
  ---
555
555
  ### 14 - Window Function
556
556
 
557
- Aggregation functions (Avg, Min, Max, Sum, Count) have the **over** method...
557
+ Aggregation functions (Avg, Min, Max, Sum, Count) -- or Window functions (Lead, Lag, Row_Number, Rank) -- have the **over** method...
558
558
 
559
559
  query=Select(
560
560
  'Enrollment e',
561
561
  payment=Sum().over(
562
- partition='student_id', order='due_date'
562
+ student_id=Partition, due_date=OrderBy,
563
+ # _=Rows(Current(), Following(5)),
564
+ # ^^^-------> ROWS BETWEEN CURRENT ROW AND 5 FOLLOWING
565
+ # _=Rows(Preceding(3), Following()),
566
+ # ^^^-------> ROWS BETWEEN 3 PRECEDING AND UNBOUNDED FOLLOWING
567
+ # _=Rows(Preceding(3))
568
+ # ^^^-------> ROWS 3 PRECEDING
563
569
  ).As('sum_per_student')
564
570
  )
565
571
 
@@ -0,0 +1,7 @@
1
+ sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
2
+ sql_blocks/sql_blocks.py,sha256=iFS3drlQaazFkbBBFIH58RPZt4Lhe6R2Xqi_Ujef7Bg,51893
3
+ sql_blocks-1.25.1801.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
+ sql_blocks-1.25.1801.dist-info/METADATA,sha256=WnwFnhle4YXNyeC6dBVAnQmUqJiboT1CDhbvRHOmEQY,15027
5
+ sql_blocks-1.25.1801.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
+ sql_blocks-1.25.1801.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
+ sql_blocks-1.25.1801.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
2
- sql_blocks/sql_blocks.py,sha256=Saj3MqmF0OHY60bhc_aSl8fL-PhXM2apmiPiE6KspOc,50553
3
- sql_blocks-1.25.113.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
- sql_blocks-1.25.113.dist-info/METADATA,sha256=td1IZl9O3m2U0rWFk6gyecqWnkr0cMDW94PfeqhzP8Y,14638
5
- sql_blocks-1.25.113.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
- sql_blocks-1.25.113.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
- sql_blocks-1.25.113.dist-info/RECORD,,