sql-blocks 0.2.0__py3-none-any.whl → 0.2.2__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
@@ -4,15 +4,14 @@ import re
4
4
 
5
5
  PATTERN_PREFIX = '([^0-9 ]+[.])'
6
6
  PATTERN_SUFFIX = '( [A-Za-z_]+)'
7
- SUFFIX_AND_PRE = f'{PATTERN_SUFFIX}|{PATTERN_PREFIX}'
8
- DISTINCT_PREFX = f'(DISTINCT|distinct)|{PATTERN_PREFIX}'
7
+ DISTINCT_PREFX = '(DISTINCT|distinct)'
9
8
 
10
9
  KEYWORD = {
11
10
  'SELECT': (',{}', 'SELECT *', DISTINCT_PREFX),
12
11
  'FROM': ('{}', '', PATTERN_SUFFIX),
13
12
  'WHERE': ('{}AND ', '', ''),
14
- 'GROUP BY': (',{}', '', SUFFIX_AND_PRE),
15
- 'ORDER BY': (',{}', '', SUFFIX_AND_PRE),
13
+ 'GROUP BY': (',{}', '', PATTERN_SUFFIX),
14
+ 'ORDER BY': (',{}', '', PATTERN_SUFFIX),
16
15
  'LIMIT': (' ', '', ''),
17
16
  }
18
17
  # ^ ^ ^
@@ -69,16 +68,18 @@ class SQLObject:
69
68
  appendix = {WHERE: 'and|', FROM: 'join|JOIN'}
70
69
  return KEYWORD[key][0].format(appendix.get(key, ''))
71
70
 
72
- def diff(self, key: str, search_list: list, symmetrical: bool=False) -> set:
71
+ def diff(self, key: str, search_list: list, exact: bool=False) -> set:
73
72
  def cleanup(fld: str) -> str:
74
- if symmetrical:
73
+ if exact:
75
74
  fld = fld.lower()
76
75
  return fld.strip()
77
76
  def is_named_field(fld: str) -> bool:
78
77
  return key == SELECT and re.search(' as | AS ', fld)
79
78
  pattern = KEYWORD[key][2]
80
- if key == WHERE and symmetrical:
81
- pattern = f'{PATTERN_PREFIX}| '
79
+ if exact:
80
+ if key == WHERE:
81
+ pattern = ' '
82
+ pattern += f'|{PATTERN_PREFIX}'
82
83
  separator = self.get_separator(key)
83
84
  def field_set(source: list) -> set:
84
85
  return set(
@@ -91,7 +92,7 @@ class SQLObject:
91
92
  )
92
93
  s1 = field_set(search_list)
93
94
  s2 = field_set(self.values.get(key, []))
94
- if symmetrical:
95
+ if exact:
95
96
  return s1.symmetric_difference(s2)
96
97
  return s1 - s2
97
98
 
@@ -247,7 +248,7 @@ class Where:
247
248
  return cls.__constructor('=', value)
248
249
 
249
250
  @classmethod
250
- def like(cls, value: str):
251
+ def contains(cls, value: str):
251
252
  return cls(f"LIKE '%{value}%'")
252
253
 
253
254
  @classmethod
@@ -271,7 +272,7 @@ class Where:
271
272
  return cls('IS NULL')
272
273
 
273
274
  @classmethod
274
- def contains(cls, values):
275
+ def inside(cls, values):
275
276
  if isinstance(values, list):
276
277
  values = ','.join(quoted(v) for v in values)
277
278
  return cls(f'IN ({values})')
@@ -282,9 +283,9 @@ class Where:
282
283
  ))
283
284
 
284
285
 
285
- eq, like, gt, gte, lt, lte, is_null, contains = (
286
+ eq, contains, gt, gte, lt, lte, is_null, inside = (
286
287
  getattr(Where, method) for method in
287
- ('eq', 'like', 'gt', 'gte', 'lt', 'lte', 'is_null', 'contains')
288
+ ('eq', 'contains', 'gt', 'gte', 'lt', 'lte', 'is_null', 'inside')
288
289
  )
289
290
 
290
291
 
@@ -447,23 +448,25 @@ class Select(SQLObject):
447
448
  main.update_values(key, self.values.get(key, []))
448
449
 
449
450
  def __add__(self, other: SQLObject):
450
- if self.table_name.lower() == other.table_name.lower():
451
+ from copy import deepcopy
452
+ query = deepcopy(self)
453
+ if query.table_name.lower() == other.table_name.lower():
451
454
  for key in USUAL_KEYS:
452
- self.update_values(key, other.values.get(key, []))
453
- return self
454
- foreign_field, primary_key = ForeignKey.find(self, other)
455
+ query.update_values(key, other.values.get(key, []))
456
+ return query
457
+ foreign_field, primary_key = ForeignKey.find(query, other)
455
458
  if not foreign_field:
456
- foreign_field, primary_key = ForeignKey.find(other, self)
459
+ foreign_field, primary_key = ForeignKey.find(other, query)
457
460
  if foreign_field:
458
461
  if primary_key:
459
- PrimaryKey.add(primary_key, self)
460
- self.add(foreign_field, other)
462
+ PrimaryKey.add(primary_key, query)
463
+ query.add(foreign_field, other)
461
464
  return other
462
- raise ValueError(f'No relationship found between {self.table_name} and {other.table_name}.')
465
+ raise ValueError(f'No relationship found between {query.table_name} and {other.table_name}.')
463
466
  elif primary_key:
464
467
  PrimaryKey.add(primary_key, other)
465
- other.add(foreign_field, self)
466
- return self
468
+ other.add(foreign_field, query)
469
+ return query
467
470
 
468
471
  def __str__(self) -> str:
469
472
  TABULATION = '\n\t' if self.break_lines else ' '
@@ -590,7 +593,7 @@ class SelectIN(Select):
590
593
 
591
594
  def add(self, name: str, main: SQLObject):
592
595
  self.break_lines = False
593
- self.condition_class.contains(self).add(name, main)
596
+ self.condition_class.inside(self).add(name, main)
594
597
 
595
598
  SubSelect = SelectIN
596
599
 
@@ -644,7 +647,7 @@ class RuleLogicalOp(Rule):
644
647
  ))
645
648
  for i, condition in enumerate(target.values.get(WHERE, [])):
646
649
  expr = re.sub('\n|\t', ' ', condition)
647
- if not re.search(r'\b(NOT|not)\b', expr):
650
+ if not re.search(r'\b(NOT|not).*[<>=]', expr):
648
651
  continue
649
652
  tokens = [t.strip() for t in re.split(r'NOT\b|not\b|(<|>|=)', expr) if t]
650
653
  op = ''.join(tokens[1: len(tokens)-1])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sql_blocks
3
- Version: 0.2.0
3
+ Version: 0.2.2
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
@@ -24,7 +24,7 @@ _Note that an alias "act" has been added._
24
24
  You can specify your own alias: `a = Select('Actor a')`
25
25
 
26
26
  ---
27
- ### 2 - You can also add a field, like this...
27
+ ### 2 - You can also add a field, contains this...
28
28
 
29
29
  * a = Select('Actor a', **name=Field**)
30
30
 
@@ -62,11 +62,13 @@ You can specify your own alias: `a = Select('Actor a')`
62
62
  * field=gt(value) - ...the field is GREATER than the value;
63
63
  * field=lt(value) - ...the field is LESS than the value;
64
64
 
65
- 3.1 -- If you want to filter the field on a range of values:
66
-
67
- `a = Select( 'Actor a', age=Between(45, 69) )`
65
+ > You may use Where.**eq**, Where.**gt**, Where.**lt** ... or simply **eq**, **gt**, **lt** ... 😉
66
+
67
+ 3.1 -- If you want to filter the field on a range of values:
68
+
69
+ `a = Select( 'Actor a', age=Between(45, 69) )`
68
70
 
69
- 3.2 -- Sub-queries:
71
+ 3.2 -- Sub-queries:
70
72
  ```
71
73
  query = Select('Movie m', title=Field,
72
74
  id=SelectIN(
@@ -93,7 +95,7 @@ query = Select('Movie m', title=Field,
93
95
  ```
94
96
  OR=Options(
95
97
  genre=eq("Sci-Fi"),
96
- awards=like("Oscar")
98
+ awards=contains("Oscar")
97
99
  )
98
100
  ```
99
101
  > Could be AND=Options(...)
@@ -105,7 +107,7 @@ based_on_book=Not.is_null()
105
107
 
106
108
  3.5 -- List of values
107
109
  ```
108
- hash_tag=contains(['space', 'monster', 'gore'])
110
+ hash_tag=inside(['space', 'monster', 'gore'])
109
111
  ```
110
112
 
111
113
  ---
@@ -113,7 +115,7 @@ hash_tag=contains(['space', 'monster', 'gore'])
113
115
 
114
116
  * m = Select('Movie m' release_date=[Field, OrderBy])
115
117
  - This means that the field will appear in the results and also that the query will be ordered by that field.
116
- * Applying **GROUP BY** to item 3.2, it would look like this:
118
+ * Applying **GROUP BY** to item 3.2, it would look contains this:
117
119
  ```
118
120
  SelectIN(
119
121
  'Review r', movie=[GroupBy, Distinct],
@@ -0,0 +1,7 @@
1
+ sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
2
+ sql_blocks/sql_blocks.py,sha256=uzMAPjx1d7CAb5WLoel_RcC91Onx3cFVQzGaww-VYEc,21552
3
+ sql_blocks-0.2.2.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
+ sql_blocks-0.2.2.dist-info/METADATA,sha256=izh5P3AG_LTwdBJyqpPwntbFXVlolK2kmhVKPmr_6dk,8892
5
+ sql_blocks-0.2.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
+ sql_blocks-0.2.2.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
+ sql_blocks-0.2.2.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
2
- sql_blocks/sql_blocks.py,sha256=Fg7yPeASygx7c7Nct5yKurxRrnjVGsvp4RnR93Wwems,21519
3
- sql_blocks-0.2.0.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
- sql_blocks-0.2.0.dist-info/METADATA,sha256=CU4oSLqoycnvhkPROx_SSbj9zJjCwwz4JoePIgk4wSE,8794
5
- sql_blocks-0.2.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
- sql_blocks-0.2.0.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
- sql_blocks-0.2.0.dist-info/RECORD,,