sql-blocks 0.0.4__py3-none-any.whl → 0.0.6__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/__init__.py CHANGED
@@ -1 +1 @@
1
- from sql_blocks import *
1
+ from sql_blocks.sql_blocks import *
sql_blocks/sql_blocks.py CHANGED
@@ -2,14 +2,27 @@ from enum import Enum
2
2
  import re
3
3
 
4
4
 
5
+ PATTERN_PREFIX = '([^0-9 ]+[.])'
6
+ PATTERN_SUFFIX = '( [A-Za-z_]+)'
7
+ SUFFIX_AND_PRE = f'{PATTERN_SUFFIX}|{PATTERN_PREFIX}'
8
+ DISTINCT_SF_PR = f'(DISTINCT|distinct)|{SUFFIX_AND_PRE}'
9
+
5
10
  KEYWORD = {
6
- 'SELECT': (',{}', 'SELECT *'),
7
- 'FROM': ('{}', ''),
8
- 'WHERE': ('{}AND ', ''),
9
- 'GROUP BY': (',{}', ''),
10
- 'ORDER BY': (',{}', ''),
11
- 'LIMIT': (' ', ''),
11
+ 'SELECT': (',{}', 'SELECT *', DISTINCT_SF_PR),
12
+ 'FROM': ('{}', '', PATTERN_SUFFIX),
13
+ 'WHERE': ('{}AND ', '', PATTERN_PREFIX),
14
+ 'GROUP BY': (',{}', '', SUFFIX_AND_PRE),
15
+ 'ORDER BY': (',{}', '', SUFFIX_AND_PRE),
16
+ 'LIMIT': (' ', '', ''),
12
17
  }
18
+ # ^ ^ ^
19
+ # | | |
20
+ # | | +----- pattern to compare fields
21
+ # | |
22
+ # | +----- default when empty (SELECT * ...)
23
+ # |
24
+ # +-------- separator
25
+
13
26
  SELECT, FROM, WHERE, GROUP_BY, ORDER_BY, LIMIT = KEYWORD.keys()
14
27
  USUAL_KEYS = [SELECT, WHERE, GROUP_BY, ORDER_BY]
15
28
 
@@ -39,6 +52,26 @@ class SQLObject:
39
52
  def table_name(self) -> str:
40
53
  return self.values[FROM][0].split()[0]
41
54
 
55
+ @staticmethod
56
+ def get_separator(key: str) -> str:
57
+ appendix = {WHERE: 'and|', FROM: 'join|JOIN'}
58
+ return KEYWORD[key][0].format(appendix.get(key, ''))
59
+
60
+ def diff(self, key: str, search_list: list, symmetrical: bool=False) -> set:
61
+ pattern = KEYWORD[key][2]
62
+ separator = self.get_separator(key)
63
+ def field_set(source: list) -> set:
64
+ return set(
65
+ re.sub(pattern, '', fld.strip()).lower()
66
+ for string in source
67
+ for fld in re.split(separator, string)
68
+ )
69
+ s1 = field_set(search_list)
70
+ s2 = field_set(self.values.get(key, []))
71
+ if symmetrical:
72
+ return s1.symmetric_difference(s2)
73
+ return s1 - s2
74
+
42
75
  def delete(self, search: str, keys: list=USUAL_KEYS):
43
76
  for key in keys:
44
77
  result = []
@@ -329,13 +362,12 @@ class Select(SQLObject):
329
362
  self.__call__(**values)
330
363
  self.break_lines = True
331
364
 
365
+ def update_values(self, key: str, new_values: list):
366
+ for value in self.diff(key, new_values):
367
+ self.values.setdefault(key, []).append(value)
368
+
332
369
  def add(self, name: str, main: SQLObject):
333
- def update_values(key: str, new_values: list):
334
- for value in new_values:
335
- old_values = main.values.get(key, [])
336
- if value not in old_values:
337
- main.values[key] = old_values + [value]
338
- update_values(
370
+ main.update_values(
339
371
  FROM, [
340
372
  '{jt}JOIN {tb} {a2} ON ({a1}.{f1} = {a2}.{f2})'.format(
341
373
  jt=self.join_type.value,
@@ -346,9 +378,13 @@ class Select(SQLObject):
346
378
  ] + self.values[FROM][1:]
347
379
  )
348
380
  for key in USUAL_KEYS:
349
- update_values(key, self.values.get(key, []))
381
+ main.update_values(key, self.values.get(key, []))
350
382
 
351
383
  def __add__(self, other: SQLObject):
384
+ if self.table_name.lower() == other.table_name.lower():
385
+ for key in USUAL_KEYS:
386
+ self.update_values(key, other.values.get(key, []))
387
+ return self
352
388
  foreign_field, primary_key = ForeignKey.find(self, other)
353
389
  if not foreign_field:
354
390
  foreign_field, primary_key = ForeignKey.find(other, self)
@@ -383,10 +419,8 @@ class Select(SQLObject):
383
419
  return self
384
420
 
385
421
  def __eq__(self, other: SQLObject) -> bool:
386
- def sorted_values(obj: SQLObject, key: str) -> list:
387
- return sorted(obj.values.get(key, []))
388
422
  for key in KEYWORD:
389
- if sorted_values(self, key) != sorted_values(other, key):
423
+ if self.diff(key, other.values.get(key, []), True):
390
424
  return False
391
425
  return True
392
426
 
@@ -427,7 +461,7 @@ class Select(SQLObject):
427
461
  inner = txt[start: end]
428
462
  if inner.count('(') > inner.count(')'):
429
463
  end = find_parenthesis(end)
430
- inner = txt[start: end]
464
+ inner = txt[start: end-1]
431
465
  fld, *inner = re.split(r' IN | in', inner, maxsplit=1)
432
466
  if fld.upper() == 'NOT':
433
467
  pos = find_last_word(start)
@@ -457,15 +491,12 @@ class Select(SQLObject):
457
491
  for key in USUAL_KEYS:
458
492
  if not key in values:
459
493
  continue
460
- separator = KEYWORD[key][0].format('')
461
- fields = [
494
+ separator = cls.get_separator(key)
495
+ obj.values[key] = [
462
496
  Field.format(fld, obj)
463
- for fld in re.split(
464
- separator, values[key]
465
- ) if len(tables) == 1
466
- or re.findall(f'\b*{obj.alias}[.]', fld)
497
+ for fld in re.split(separator, values[key])
498
+ if len(tables) == 1 or re.findall(f'\b*{obj.alias}[.]', fld)
467
499
  ]
468
- obj.values[key] = [ f for f in fields if f.strip() ]
469
500
  result[obj.alias] = obj
470
501
  return list( result.values() )
471
502
 
@@ -480,32 +511,3 @@ SubSelect = SelectIN
480
511
 
481
512
  class NotSelectIN(SelectIN):
482
513
  condition_class = Not
483
-
484
-
485
- if __name__ == "__main__":
486
- query_list = Select.parse("""
487
- SELECT
488
- cas.role,
489
- m.title,
490
- m.release_date,
491
- a.name as actors_name
492
- FROM
493
- Actor a
494
- LEFT JOIN Cast cas ON (a.cast = cas.id)
495
- LEFT JOIN Movie m ON (cas.movie = m.id)
496
- WHERE
497
- m.genre NOT in (SELECT g.id from Genres g where g.name in ('sci-fi', 'horror', 'distopia'))
498
- AND (m.hashtag = '#cult' OR m.awards LIKE '%Oscar%')
499
- AND m.id IN (select DISTINCT r.movie FROM Review r GROUP BY r.movie HAVING Avg(r.rate) > 4.5)
500
- AND a.age <= 69 AND a.age >= 45
501
- ORDER BY
502
- m.release_date
503
- """)
504
- for query in query_list:
505
- descr = ' {} ({}) '.format(
506
- query.table_name,
507
- query.__class__.__name__
508
- )
509
- print(descr.center(50, '-'))
510
- print(query)
511
- print('='*50)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sql_blocks
3
- Version: 0.0.4
3
+ Version: 0.0.6
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
@@ -249,13 +249,13 @@ m = Select...
249
249
  9.1
250
250
  ```
251
251
  a1 = Select.parse('''
252
- SELECT gender, max(age) FROM Actor act
252
+ SELECT gender, Max(act.age) FROM Actor act
253
253
  WHERE act.age <= 69 AND act.age >= 45
254
254
  GROUP BY gender
255
255
  ''')[0]
256
256
 
257
257
  a2 = Select('Actor',
258
- age=Between(45, 69), gender=GroupBy,
258
+ age=[ Between(45, 69), Max ],
259
259
  gender=[GroupBy, Field]
260
260
  )
261
261
  ```
@@ -306,9 +306,9 @@ m2 = Select(
306
306
  Select(
307
307
  'Product',
308
308
  label=Case('price').when(
309
- lt(50), 'cheap'
309
+ Where.lt(50), 'cheap'
310
310
  ).when(
311
- gt(100), 'expensive'
311
+ Where.gt(100), 'expensive'
312
312
  ).else_value(
313
313
  'normal'
314
314
  )
@@ -0,0 +1,7 @@
1
+ sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
2
+ sql_blocks/sql_blocks.py,sha256=Fs636uSwXTxlzHH9SCOxmGTgt2MjhQ6Pf6v92CRtQ9E,16229
3
+ sql_blocks-0.0.6.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
+ sql_blocks-0.0.6.dist-info/METADATA,sha256=-2-vPw1nkpqKvlp0l2Bt8VF_sBZ_TM8BGf-Nmk8X2oo,7037
5
+ sql_blocks-0.0.6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
+ sql_blocks-0.0.6.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
+ sql_blocks-0.0.6.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- sql_blocks/__init__.py,sha256=TodC5q-UEdYEz9v1RRoogVqqRcsKnZRY1WDGinrI2zo,26
2
- sql_blocks/sql_blocks.py,sha256=CX8rJtDvL07eGjwJbiqRKDckvrosJf4_PEBw5SK8mrQ,16051
3
- sql_blocks-0.0.4.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
- sql_blocks-0.0.4.dist-info/METADATA,sha256=RoaYK32YS_CAW2UBogLABwxIPPwjqcmZH1EQh-iA2ZQ,7028
5
- sql_blocks-0.0.4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
- sql_blocks-0.0.4.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
- sql_blocks-0.0.4.dist-info/RECORD,,