sql-blocks 1.25.112__py3-none-any.whl → 1.25.113__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
@@ -70,6 +70,10 @@ class SQLObject:
70
70
  appendix = {WHERE: r'\s+and\s+|', FROM: r'\s+join\s+|\s+JOIN\s+'}
71
71
  return KEYWORD[key][0].format(appendix.get(key, ''))
72
72
 
73
+ @staticmethod
74
+ def is_named_field(fld: str, key: str) -> bool:
75
+ return key == SELECT and re.search(r'\s+as\s+|\s+AS\s+', fld)
76
+
73
77
  def diff(self, key: str, search_list: list, exact: bool=False) -> set:
74
78
  def disassemble(source: list) -> list:
75
79
  if not exact:
@@ -82,12 +86,10 @@ class SQLObject:
82
86
  if exact:
83
87
  fld = fld.lower()
84
88
  return fld.strip()
85
- def is_named_field(fld: str) -> bool:
86
- return key == SELECT and re.search(r'\s+as\s+|\s+AS\s+', fld)
87
89
  def field_set(source: list) -> set:
88
90
  return set(
89
91
  (
90
- fld if is_named_field(fld) else
92
+ fld if self.is_named_field(fld, key) else
91
93
  re.sub(pattern, '', cleanup(fld))
92
94
  )
93
95
  for string in disassemble(source)
@@ -105,13 +107,16 @@ class SQLObject:
105
107
  return s1.symmetric_difference(s2)
106
108
  return s1 - s2
107
109
 
108
- def delete(self, search: str, keys: list=USUAL_KEYS):
110
+ def delete(self, search: str, keys: list=USUAL_KEYS, exact: bool=False):
111
+ if exact:
112
+ not_match = lambda item: not re.search(fr'\w*[.]*{search}$', item)
113
+ else:
114
+ not_match = lambda item: search not in item
109
115
  for key in keys:
110
- result = []
111
- for item in self.values.get(key, []):
112
- if search not in item:
113
- result.append(item)
114
- self.values[key] = result
116
+ self.values[key] = [
117
+ item for item in self.values.get(key, [])
118
+ if not_match(item)
119
+ ]
115
120
 
116
121
 
117
122
  SQL_CONST_SYSDATE = 'SYSDATE'
@@ -961,7 +966,7 @@ class SQLParser(Parser):
961
966
  obj.values[key] = [
962
967
  Field.format(fld, obj)
963
968
  for fld in re.split(separator, values[key])
964
- if (fld != '*' and len(tables) == 1) or obj.match(fld)
969
+ if (fld != '*' and len(tables) == 1) or obj.match(fld, key)
965
970
  ]
966
971
  result[obj.alias] = obj
967
972
  self.queries = list( result.values() )
@@ -1026,8 +1031,9 @@ class CypherParser(Parser):
1026
1031
  if func_name == 'count':
1027
1032
  if not token:
1028
1033
  token = 'count_1'
1029
- NamedField(token, Count).add('*', self.queries[-1])
1030
- class_list = []
1034
+ pk_field = self.queries[-1].key_field or 'id'
1035
+ Count().As(token, extra_classes).add(pk_field, self.queries[-1])
1036
+ return
1031
1037
  else:
1032
1038
  FUNCTION_CLASS = {f.__name__.lower(): f for f in Function.__subclasses__()}
1033
1039
  class_list = [ FUNCTION_CLASS[func_name] ]
@@ -1048,7 +1054,7 @@ class CypherParser(Parser):
1048
1054
  if not last.values.get(SELECT):
1049
1055
  raise IndexError(f'Primary Key not found for {last.table_name}.')
1050
1056
  pk_field = last.values[SELECT][-1].split('.')[-1]
1051
- last.delete(pk_field, [SELECT])
1057
+ last.delete(pk_field, [SELECT], exact=True)
1052
1058
  if '{}' in token:
1053
1059
  foreign_fld = token.format(
1054
1060
  last.table_name.lower()
@@ -1063,12 +1069,11 @@ class CypherParser(Parser):
1063
1069
  if fld not in curr.values.get(GROUP_BY, [])
1064
1070
  ]
1065
1071
  foreign_fld = fields[0].split('.')[-1]
1066
- curr.delete(foreign_fld, [SELECT])
1072
+ curr.delete(foreign_fld, [SELECT], exact=True)
1067
1073
  if curr.join_type == JoinType.RIGHT:
1068
1074
  pk_field, foreign_fld = foreign_fld, pk_field
1069
1075
  if curr.join_type == JoinType.RIGHT:
1070
1076
  curr, last = last, curr
1071
- # pk_field, foreign_fld = foreign_fld, pk_field
1072
1077
  k = ForeignKey.get_key(curr, last)
1073
1078
  ForeignKey.references[k] = (foreign_fld, pk_field)
1074
1079
 
@@ -1309,8 +1314,17 @@ class Select(SQLObject):
1309
1314
  self.values.setdefault(LIMIT, result)
1310
1315
  return self
1311
1316
 
1312
- def match(self, expr: str) -> bool:
1313
- return re.findall(f'\b*{self.alias}[.]', expr) != []
1317
+ def match(self, field: str, key: str) -> bool:
1318
+ '''
1319
+ Recognizes if the field is from the current table
1320
+ '''
1321
+ if key in (ORDER_BY, GROUP_BY) and '.' not in field:
1322
+ return any(
1323
+ self.is_named_field(fld, SELECT)
1324
+ for fld in self.values[SELECT]
1325
+ if field in fld
1326
+ )
1327
+ return re.findall(f'\b*{self.alias}[.]', field) != []
1314
1328
 
1315
1329
  @classmethod
1316
1330
  def parse(cls, txt: str, parser: Parser = SQLParser) -> list[SQLObject]:
@@ -1431,12 +1445,13 @@ class RuleReplaceJoinBySubselect(Rule):
1431
1445
  more_relations = any([
1432
1446
  ref[0] == query.table_name for ref in ForeignKey.references
1433
1447
  ])
1434
- invalid = any([
1448
+ keep_join = any([
1435
1449
  len( query.values.get(SELECT, []) ) > 0,
1436
1450
  len( query.values.get(WHERE, []) ) == 0,
1437
1451
  not fk_field, more_relations
1438
1452
  ])
1439
- if invalid:
1453
+ if keep_join:
1454
+ query.add(fk_field, main)
1440
1455
  continue
1441
1456
  query.__class__ = SubSelect
1442
1457
  Field.add(primary_k, query)
@@ -1482,3 +1497,16 @@ def detect(text: str) -> Select:
1482
1497
  return result
1483
1498
 
1484
1499
 
1500
+ 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('#######################################')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sql_blocks
3
- Version: 1.25.112
3
+ Version: 1.25.113
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
@@ -0,0 +1,7 @@
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,,
@@ -1,7 +0,0 @@
1
- sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
2
- sql_blocks/sql_blocks.py,sha256=X13qSCvVhu-BVXdUmqXi48Z7H4THBvXHrP5zw2Hm4wM,49491
3
- sql_blocks-1.25.112.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
- sql_blocks-1.25.112.dist-info/METADATA,sha256=npxMGB0xgAFt4J_IgoIaaWmVFcVoNu5lq3qnUAjhb-A,14638
5
- sql_blocks-1.25.112.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
- sql_blocks-1.25.112.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
- sql_blocks-1.25.112.dist-info/RECORD,,