sql-blocks 0.1.3__tar.gz → 0.2.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sql_blocks
3
- Version: 0.1.3
3
+ Version: 0.2.0
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
@@ -55,12 +55,12 @@ You can specify your own alias: `a = Select('Actor a')`
55
55
  ---
56
56
 
57
57
  ### 3 - To set conditions, use **Where**:
58
- * For example, `a = Select(... age=Where.gt(45) )`
58
+ * For example, `a = Select(... age=gt(45) )`
59
59
 
60
60
  Some possible conditions:
61
- * field=Where.eq(value) - ...the field is EQUAL to the value;
62
- * field=Where.gt(value) - ...the field is GREATER than the value;
63
- * field=Where.lt(value) - ...the field is LESS than the value;
61
+ * field=eq(value) - ...the field is EQUAL to the value;
62
+ * field=gt(value) - ...the field is GREATER than the value;
63
+ * field=lt(value) - ...the field is LESS than the value;
64
64
 
65
65
  3.1 -- If you want to filter the field on a range of values:
66
66
 
@@ -71,7 +71,7 @@ You can specify your own alias: `a = Select('Actor a')`
71
71
  query = Select('Movie m', title=Field,
72
72
  id=SelectIN(
73
73
  'Review r',
74
- rate=Where.gt(4.5),
74
+ rate=gt(4.5),
75
75
  movie_id=Distinct
76
76
  )
77
77
  )
@@ -92,8 +92,8 @@ query = Select('Movie m', title=Field,
92
92
  3.3 -- Optional conditions:
93
93
  ```
94
94
  OR=Options(
95
- genre=Where.eq("Sci-Fi"),
96
- awards=Where.like("Oscar")
95
+ genre=eq("Sci-Fi"),
96
+ awards=like("Oscar")
97
97
  )
98
98
  ```
99
99
  > Could be AND=Options(...)
@@ -105,7 +105,7 @@ based_on_book=Not.is_null()
105
105
 
106
106
  3.5 -- List of values
107
107
  ```
108
- hash_tag=Where.list(['space', 'monster', 'gore'])
108
+ hash_tag=contains(['space', 'monster', 'gore'])
109
109
  ```
110
110
 
111
111
  ---
@@ -117,7 +117,7 @@ hash_tag=Where.list(['space', 'monster', 'gore'])
117
117
  ```
118
118
  SelectIN(
119
119
  'Review r', movie=[GroupBy, Distinct],
120
- rate=Having.avg(Where.gt(4.5))
120
+ rate=Having.avg(gt(4.5))
121
121
  )
122
122
  ```
123
123
  ---
@@ -299,7 +299,7 @@ m = Select...
299
299
  ```
300
300
  best_movies = SelectIN(
301
301
  Review=Table('role'),
302
- rate=[GroupBy, Having.avg(Where.gt(4.5))]
302
+ rate=[GroupBy, Having.avg(gt(4.5))]
303
303
  )
304
304
  m1 = Select(
305
305
  Movie=Table('title,release_date'),
@@ -320,9 +320,9 @@ m2 = Select(
320
320
  Select(
321
321
  'Product',
322
322
  label=Case('price').when(
323
- Where.lt(50), 'cheap'
323
+ lt(50), 'cheap'
324
324
  ).when(
325
- Where.gt(100), 'expensive'
325
+ gt(100), 'expensive'
326
326
  ).else_value(
327
327
  'normal'
328
328
  )
@@ -360,3 +360,22 @@ m2 = Select(
360
360
  * Replace `YEAR` function with date range comparison.
361
361
 
362
362
  > The method allows you to select which rules you want to apply in the optimization...Or define your own rules!
363
+
364
+ ---
365
+
366
+ ### 12 - Adding multiple fields at once
367
+ ```
368
+ query = Select('post p')
369
+ query.add_fields(
370
+ 'user_id, created_at',
371
+ order_by=True, group_by=True
372
+ )
373
+ ```
374
+ ...is the same as...
375
+ ```
376
+ query = Select(
377
+ 'post p',
378
+ user_id=[Field, GroupBy, OrderBy],
379
+ created_at=[Field, GroupBy, OrderBy]
380
+ )
381
+ ```
@@ -40,12 +40,12 @@ You can specify your own alias: `a = Select('Actor a')`
40
40
  ---
41
41
 
42
42
  ### 3 - To set conditions, use **Where**:
43
- * For example, `a = Select(... age=Where.gt(45) )`
43
+ * For example, `a = Select(... age=gt(45) )`
44
44
 
45
45
  Some possible conditions:
46
- * field=Where.eq(value) - ...the field is EQUAL to the value;
47
- * field=Where.gt(value) - ...the field is GREATER than the value;
48
- * field=Where.lt(value) - ...the field is LESS than the value;
46
+ * field=eq(value) - ...the field is EQUAL to the value;
47
+ * field=gt(value) - ...the field is GREATER than the value;
48
+ * field=lt(value) - ...the field is LESS than the value;
49
49
 
50
50
  3.1 -- If you want to filter the field on a range of values:
51
51
 
@@ -56,7 +56,7 @@ You can specify your own alias: `a = Select('Actor a')`
56
56
  query = Select('Movie m', title=Field,
57
57
  id=SelectIN(
58
58
  'Review r',
59
- rate=Where.gt(4.5),
59
+ rate=gt(4.5),
60
60
  movie_id=Distinct
61
61
  )
62
62
  )
@@ -77,8 +77,8 @@ query = Select('Movie m', title=Field,
77
77
  3.3 -- Optional conditions:
78
78
  ```
79
79
  OR=Options(
80
- genre=Where.eq("Sci-Fi"),
81
- awards=Where.like("Oscar")
80
+ genre=eq("Sci-Fi"),
81
+ awards=like("Oscar")
82
82
  )
83
83
  ```
84
84
  > Could be AND=Options(...)
@@ -90,7 +90,7 @@ based_on_book=Not.is_null()
90
90
 
91
91
  3.5 -- List of values
92
92
  ```
93
- hash_tag=Where.list(['space', 'monster', 'gore'])
93
+ hash_tag=contains(['space', 'monster', 'gore'])
94
94
  ```
95
95
 
96
96
  ---
@@ -102,7 +102,7 @@ hash_tag=Where.list(['space', 'monster', 'gore'])
102
102
  ```
103
103
  SelectIN(
104
104
  'Review r', movie=[GroupBy, Distinct],
105
- rate=Having.avg(Where.gt(4.5))
105
+ rate=Having.avg(gt(4.5))
106
106
  )
107
107
  ```
108
108
  ---
@@ -284,7 +284,7 @@ m = Select...
284
284
  ```
285
285
  best_movies = SelectIN(
286
286
  Review=Table('role'),
287
- rate=[GroupBy, Having.avg(Where.gt(4.5))]
287
+ rate=[GroupBy, Having.avg(gt(4.5))]
288
288
  )
289
289
  m1 = Select(
290
290
  Movie=Table('title,release_date'),
@@ -305,9 +305,9 @@ m2 = Select(
305
305
  Select(
306
306
  'Product',
307
307
  label=Case('price').when(
308
- Where.lt(50), 'cheap'
308
+ lt(50), 'cheap'
309
309
  ).when(
310
- Where.gt(100), 'expensive'
310
+ gt(100), 'expensive'
311
311
  ).else_value(
312
312
  'normal'
313
313
  )
@@ -344,4 +344,23 @@ m2 = Select(
344
344
  * Auto includes fields present in `ORDER/GROUP BY`;
345
345
  * Replace `YEAR` function with date range comparison.
346
346
 
347
- > The method allows you to select which rules you want to apply in the optimization...Or define your own rules!
347
+ > The method allows you to select which rules you want to apply in the optimization...Or define your own rules!
348
+
349
+ ---
350
+
351
+ ### 12 - Adding multiple fields at once
352
+ ```
353
+ query = Select('post p')
354
+ query.add_fields(
355
+ 'user_id, created_at',
356
+ order_by=True, group_by=True
357
+ )
358
+ ```
359
+ ...is the same as...
360
+ ```
361
+ query = Select(
362
+ 'post p',
363
+ user_id=[Field, GroupBy, OrderBy],
364
+ created_at=[Field, GroupBy, OrderBy]
365
+ )
366
+ ```
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sql_blocks"
3
- version = "0.1.3"
3
+ version = "0.2.0"
4
4
  authors = [
5
5
  { name="Julio Cascalles", email="julio.cascalles@outlook.com" },
6
6
  ]
@@ -3,7 +3,7 @@ from setuptools import setup
3
3
 
4
4
  setup(
5
5
  name = 'sql_blocks',
6
- version = '0.1.3',
6
+ version = '0.2.0',
7
7
  author = 'Júlio Cascalles',
8
8
  author_email = 'julio.cascalles@outlook.com',
9
9
  packages = ['sql_blocks'],
@@ -74,14 +74,18 @@ class SQLObject:
74
74
  if symmetrical:
75
75
  fld = fld.lower()
76
76
  return fld.strip()
77
- # if key == SELECT and re.search(' as | AS ', fld)
77
+ def is_named_field(fld: str) -> bool:
78
+ return key == SELECT and re.search(' as | AS ', fld)
78
79
  pattern = KEYWORD[key][2]
79
80
  if key == WHERE and symmetrical:
80
81
  pattern = f'{PATTERN_PREFIX}| '
81
82
  separator = self.get_separator(key)
82
83
  def field_set(source: list) -> set:
83
84
  return set(
84
- re.sub(pattern, '', cleanup(fld))
85
+ (
86
+ fld if is_named_field(fld) else
87
+ re.sub(pattern, '', cleanup(fld))
88
+ )
85
89
  for string in source
86
90
  for fld in re.split(separator, string)
87
91
  )
@@ -172,17 +176,27 @@ class ExpressionField:
172
176
  a=main.alias, f=name, t=main.table_name
173
177
  )
174
178
 
179
+ class FieldList:
180
+ separator = ','
175
181
 
176
- class Table:
177
- def __init__(self, fields: list=[]):
182
+ def __init__(self, fields: list=[], class_types = [Field]):
178
183
  if isinstance(fields, str):
179
- fields = [f.strip() for f in fields.split(',')]
184
+ fields = [
185
+ f.strip() for f in fields.split(self.separator)
186
+ ]
180
187
  self.fields = fields
188
+ self.class_types = class_types
181
189
 
182
190
  def add(self, name: str, main: SQLObject):
183
- main.set_table(name)
184
191
  for field in self.fields:
185
- Field.add(field, main)
192
+ for class_type in self.class_types:
193
+ class_type.add(field, main)
194
+
195
+
196
+ class Table(FieldList):
197
+ def add(self, name: str, main: SQLObject):
198
+ main.set_table(name)
199
+ super().add(name, main)
186
200
 
187
201
 
188
202
  class PrimaryKey:
@@ -257,7 +271,7 @@ class Where:
257
271
  return cls('IS NULL')
258
272
 
259
273
  @classmethod
260
- def list(cls, values):
274
+ def contains(cls, values):
261
275
  if isinstance(values, list):
262
276
  values = ','.join(quoted(v) for v in values)
263
277
  return cls(f'IN ({values})')
@@ -268,6 +282,12 @@ class Where:
268
282
  ))
269
283
 
270
284
 
285
+ eq, like, gt, gte, lt, lte, is_null, contains = (
286
+ getattr(Where, method) for method in
287
+ ('eq', 'like', 'gt', 'gte', 'lt', 'lte', 'is_null', 'contains')
288
+ )
289
+
290
+
271
291
  class Not(Where):
272
292
  prefix = 'NOT '
273
293
 
@@ -342,9 +362,12 @@ class OrderBy:
342
362
  sort: SortType = SortType.ASC
343
363
  @classmethod
344
364
  def add(cls, name: str, main: SQLObject):
345
- if main.alias:
365
+ found = re.findall(r'^_\d', name)
366
+ if found:
367
+ name = found[0].replace('_', '')
368
+ elif main.alias:
346
369
  name = f'{main.alias}.{name}'
347
- main.values.setdefault(ORDER_BY, []).append(name + cls.sort.value)
370
+ main.values.setdefault(ORDER_BY, []).append(name+cls.sort.value)
348
371
 
349
372
 
350
373
  class GroupBy:
@@ -410,17 +433,16 @@ class Select(SQLObject):
410
433
  self.values.setdefault(key, []).append(value)
411
434
 
412
435
  def add(self, name: str, main: SQLObject):
413
- new_tables = [
436
+ old_tables = main.values.get(FROM, [])
437
+ new_tables = set([
414
438
  '{jt}JOIN {tb} {a2} ON ({a1}.{f1} = {a2}.{f2})'.format(
415
439
  jt=self.join_type.value,
416
440
  tb=self.table_name,
417
441
  a1=main.alias, f1=name,
418
442
  a2=self.alias, f2=self.key_field
419
443
  )
420
- ]
421
- if new_tables not in main.values.get(FROM, []):
422
- new_tables += self.values[FROM][1:]
423
- main.values.setdefault(FROM, []).extend(new_tables)
444
+ ] + old_tables[1:])
445
+ main.values[FROM] = old_tables[:1] + list(new_tables)
424
446
  for key in USUAL_KEYS:
425
447
  main.update_values(key, self.values.get(key, []))
426
448
 
@@ -553,13 +575,22 @@ class Select(SQLObject):
553
575
  for rule in rules:
554
576
  rule.apply(self)
555
577
 
578
+ def add_fields(self, fields: list, order_by: bool=False, group_by:bool=False):
579
+ class_types = [Field]
580
+ if order_by:
581
+ class_types += [OrderBy]
582
+ if group_by:
583
+ class_types += [GroupBy]
584
+ FieldList(fields, class_types).add('', self)
585
+
586
+
556
587
 
557
588
  class SelectIN(Select):
558
589
  condition_class = Where
559
590
 
560
591
  def add(self, name: str, main: SQLObject):
561
592
  self.break_lines = False
562
- self.condition_class.list(self).add(name, main)
593
+ self.condition_class.contains(self).add(name, main)
563
594
 
564
595
  SubSelect = SelectIN
565
596
 
@@ -574,6 +605,7 @@ class RulePutLimit(Rule):
574
605
  if need_limit:
575
606
  target.limit()
576
607
 
608
+
577
609
  class RuleSelectIN(Rule):
578
610
  @classmethod
579
611
  def apply(cls, target: Select):
@@ -588,6 +620,7 @@ class RuleSelectIN(Rule):
588
620
  ','.join(t.split('=')[-1].strip() for t in tokens)
589
621
  )
590
622
 
623
+
591
624
  class RuleAutoField(Rule):
592
625
  @classmethod
593
626
  def apply(cls, target: Select):
@@ -599,13 +632,11 @@ class RuleAutoField(Rule):
599
632
  s2 = set(target.values[ORDER_BY])
600
633
  target.values.setdefault(SELECT, []).extend( list(s2-s1) )
601
634
 
635
+
602
636
  class RuleLogicalOp(Rule):
603
- REVERSE = {
604
- ">=": "<",
605
- "<=": ">",
606
- "<>": "=",
607
- "=": "<>"
608
- }
637
+ REVERSE = {">=": "<", "<=": ">", "=": "<>"}
638
+ REVERSE |= {v: k for k, v in REVERSE.items()}
639
+
609
640
  @classmethod
610
641
  def apply(cls, target: Select):
611
642
  REGEX = re.compile('({})'.format(
@@ -613,13 +644,14 @@ class RuleLogicalOp(Rule):
613
644
  ))
614
645
  for i, condition in enumerate(target.values.get(WHERE, [])):
615
646
  expr = re.sub('\n|\t', ' ', condition)
616
- tokens = [t for t in re.split(r'(NOT\b|not\b)',expr) if t.strip()]
617
- if len(tokens) < 2 or not REGEX.findall(tokens[-1]):
647
+ if not re.search(r'\b(NOT|not)\b', expr):
618
648
  continue
619
- tokens = REGEX.split(tokens[-1])
620
- tokens[1] = cls.REVERSE[tokens[1]]
649
+ tokens = [t.strip() for t in re.split(r'NOT\b|not\b|(<|>|=)', expr) if t]
650
+ op = ''.join(tokens[1: len(tokens)-1])
651
+ tokens = [tokens[0], cls.REVERSE[op], tokens[-1]]
621
652
  target.values[WHERE][i] = ' '.join(tokens)
622
653
 
654
+
623
655
  class RuleDateFuncReplace(Rule):
624
656
  """
625
657
  SQL algorithm by Ralff Matias
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sql_blocks
3
- Version: 0.1.3
3
+ Version: 0.2.0
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
@@ -55,12 +55,12 @@ You can specify your own alias: `a = Select('Actor a')`
55
55
  ---
56
56
 
57
57
  ### 3 - To set conditions, use **Where**:
58
- * For example, `a = Select(... age=Where.gt(45) )`
58
+ * For example, `a = Select(... age=gt(45) )`
59
59
 
60
60
  Some possible conditions:
61
- * field=Where.eq(value) - ...the field is EQUAL to the value;
62
- * field=Where.gt(value) - ...the field is GREATER than the value;
63
- * field=Where.lt(value) - ...the field is LESS than the value;
61
+ * field=eq(value) - ...the field is EQUAL to the value;
62
+ * field=gt(value) - ...the field is GREATER than the value;
63
+ * field=lt(value) - ...the field is LESS than the value;
64
64
 
65
65
  3.1 -- If you want to filter the field on a range of values:
66
66
 
@@ -71,7 +71,7 @@ You can specify your own alias: `a = Select('Actor a')`
71
71
  query = Select('Movie m', title=Field,
72
72
  id=SelectIN(
73
73
  'Review r',
74
- rate=Where.gt(4.5),
74
+ rate=gt(4.5),
75
75
  movie_id=Distinct
76
76
  )
77
77
  )
@@ -92,8 +92,8 @@ query = Select('Movie m', title=Field,
92
92
  3.3 -- Optional conditions:
93
93
  ```
94
94
  OR=Options(
95
- genre=Where.eq("Sci-Fi"),
96
- awards=Where.like("Oscar")
95
+ genre=eq("Sci-Fi"),
96
+ awards=like("Oscar")
97
97
  )
98
98
  ```
99
99
  > Could be AND=Options(...)
@@ -105,7 +105,7 @@ based_on_book=Not.is_null()
105
105
 
106
106
  3.5 -- List of values
107
107
  ```
108
- hash_tag=Where.list(['space', 'monster', 'gore'])
108
+ hash_tag=contains(['space', 'monster', 'gore'])
109
109
  ```
110
110
 
111
111
  ---
@@ -117,7 +117,7 @@ hash_tag=Where.list(['space', 'monster', 'gore'])
117
117
  ```
118
118
  SelectIN(
119
119
  'Review r', movie=[GroupBy, Distinct],
120
- rate=Having.avg(Where.gt(4.5))
120
+ rate=Having.avg(gt(4.5))
121
121
  )
122
122
  ```
123
123
  ---
@@ -299,7 +299,7 @@ m = Select...
299
299
  ```
300
300
  best_movies = SelectIN(
301
301
  Review=Table('role'),
302
- rate=[GroupBy, Having.avg(Where.gt(4.5))]
302
+ rate=[GroupBy, Having.avg(gt(4.5))]
303
303
  )
304
304
  m1 = Select(
305
305
  Movie=Table('title,release_date'),
@@ -320,9 +320,9 @@ m2 = Select(
320
320
  Select(
321
321
  'Product',
322
322
  label=Case('price').when(
323
- Where.lt(50), 'cheap'
323
+ lt(50), 'cheap'
324
324
  ).when(
325
- Where.gt(100), 'expensive'
325
+ gt(100), 'expensive'
326
326
  ).else_value(
327
327
  'normal'
328
328
  )
@@ -360,3 +360,22 @@ m2 = Select(
360
360
  * Replace `YEAR` function with date range comparison.
361
361
 
362
362
  > The method allows you to select which rules you want to apply in the optimization...Or define your own rules!
363
+
364
+ ---
365
+
366
+ ### 12 - Adding multiple fields at once
367
+ ```
368
+ query = Select('post p')
369
+ query.add_fields(
370
+ 'user_id, created_at',
371
+ order_by=True, group_by=True
372
+ )
373
+ ```
374
+ ...is the same as...
375
+ ```
376
+ query = Select(
377
+ 'post p',
378
+ user_id=[Field, GroupBy, OrderBy],
379
+ created_at=[Field, GroupBy, OrderBy]
380
+ )
381
+ ```
File without changes
File without changes