sql-blocks 1.25.2__py3-none-any.whl → 1.25.109__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
@@ -26,7 +26,7 @@ TO_LIST = lambda x: x if isinstance(x, list) else [x]
26
26
 
27
27
 
28
28
  class SQLObject:
29
- ALIAS_FUNC = lambda t: t.lower()[:3]
29
+ ALIAS_FUNC = None
30
30
  """ ^^^^^^^^^^^^^^^^^^^^^^^^
31
31
  You can change the behavior by assigning
32
32
  a user function to SQLObject.ALIAS_FUNC
@@ -41,7 +41,10 @@ class SQLObject:
41
41
  def set_table(self, table_name: str):
42
42
  if not table_name:
43
43
  return
44
- if ' ' in table_name.strip():
44
+ cls = SQLObject
45
+ if cls.ALIAS_FUNC:
46
+ self.__alias = cls.ALIAS_FUNC(table_name)
47
+ elif ' ' in table_name.strip():
45
48
  table_name, self.__alias = table_name.split()
46
49
  elif '_' in table_name:
47
50
  self.__alias = ''.join(
@@ -49,7 +52,7 @@ class SQLObject:
49
52
  for word in table_name.split('_')
50
53
  )
51
54
  else:
52
- self.__alias = SQLObject.ALIAS_FUNC(table_name)
55
+ self.__alias = table_name.lower()[:3]
53
56
  self.values.setdefault(FROM, []).append(f'{table_name} {self.alias}')
54
57
 
55
58
  @property
@@ -111,15 +114,26 @@ class SQLObject:
111
114
  self.values[key] = result
112
115
 
113
116
 
117
+ SQL_CONST_SYSDATE = 'SYSDATE'
118
+ SQL_CONST_CURR_DATE = 'Current_date'
119
+ SQL_CONSTS = [SQL_CONST_SYSDATE, SQL_CONST_CURR_DATE]
120
+
121
+
114
122
  class Field:
115
123
  prefix = ''
116
124
 
117
125
  @classmethod
118
126
  def format(cls, name: str, main: SQLObject) -> str:
127
+ def is_const() -> bool:
128
+ return any([
129
+ re.findall('[.()0-9]', name),
130
+ name in SQL_CONSTS,
131
+ re.findall(r'\w+\s*[+-]\s*\w+', name)
132
+ ])
119
133
  name = name.strip()
120
134
  if name in ('_', '*'):
121
135
  name = '*'
122
- elif not re.findall('[.()0-9]', name):
136
+ elif not is_const():
123
137
  name = f'{main.alias}.{name}'
124
138
  if Function in cls.__bases__:
125
139
  name = f'{cls.__name__}({name})'
@@ -150,58 +164,69 @@ class NamedField:
150
164
  )
151
165
 
152
166
 
167
+ class Dialect(Enum):
168
+ ANSI = 0
169
+ SQL_SERVER = 1
170
+ ORACLE = 2
171
+ POSTGRESQL = 3
172
+ MYSQL = 4
173
+
153
174
  class Function:
154
- instance: dict = {}
175
+ dialect = Dialect.ANSI
155
176
 
156
177
  def __init__(self, *params: list):
157
- func_name = self.__class__.__name__
158
- Function.instance[func_name] = self
178
+ # --- Replace class methods by instance methods: ------
179
+ self.add = self.__add
180
+ self.format = self.__format
181
+ # -----------------------------------------------------
159
182
  self.params = [str(p) for p in params]
160
- self.class_type = Field
161
- self.pattern = '{}({})'
183
+ self.field_class = Field
184
+ self.pattern = self.get_pattern()
162
185
  self.extra = {}
163
186
 
187
+ def get_pattern(self) -> str:
188
+ return '{func_name}({params})'
189
+
164
190
  def As(self, field_alias: str, modifiers=None):
165
191
  if modifiers:
166
192
  self.extra[field_alias] = TO_LIST(modifiers)
167
- self.class_type = NamedField(field_alias)
193
+ self.field_class = NamedField(field_alias)
168
194
  return self
169
195
 
170
- @classmethod
171
- def format(cls, name: str, main: SQLObject) -> str:
172
- obj = cls.get_instance()
173
- if name in '*_' and obj.params:
174
- params = obj.params
175
- else:
176
- params = [
177
- Field.format(name, main)
178
- ] + obj.params
179
- return obj.pattern.format(
180
- cls.__name__,
181
- ', '.join(params)
196
+ def __str__(self) -> str:
197
+ return self.pattern.format(
198
+ func_name=self.__class__.__name__,
199
+ params=', '.join(self.params)
182
200
  )
183
201
 
202
+ def __format(self, name: str, main: SQLObject) -> str:
203
+ if name not in '*_':
204
+ self.params = [
205
+ Field.format(name, main)
206
+ ] + self.params
207
+ return str(self)
208
+
209
+ @classmethod
210
+ def format(cls, name: str, main: SQLObject):
211
+ return cls().__format(name, main)
212
+
184
213
  def __add(self, name: str, main: SQLObject):
185
214
  name = self.format(name, main)
186
- self.class_type.add(name, main)
215
+ self.field_class.add(name, main)
187
216
  if self.extra:
188
217
  main.__call__(**self.extra)
189
218
 
190
- @classmethod
191
- def get_instance(cls):
192
- obj = Function.instance.get(cls.__name__)
193
- if not obj:
194
- obj = cls()
195
- return obj
196
-
197
219
  @classmethod
198
220
  def add(cls, name: str, main: SQLObject):
199
- cls.get_instance().__add(name, main)
221
+ cls().__add(name, main)
200
222
 
201
223
 
202
224
  # ---- String Functions: ---------------------------------
203
225
  class SubString(Function):
204
- ...
226
+ def get_pattern(self) -> str:
227
+ if self.dialect in (Dialect.ORACLE, Dialect.MYSQL):
228
+ return 'Substr({params})'
229
+ return super().get_pattern()
205
230
 
206
231
  # ---- Numeric Functions: --------------------------------
207
232
  class Round(Function):
@@ -209,13 +234,37 @@ class Round(Function):
209
234
 
210
235
  # --- Date Functions: ------------------------------------
211
236
  class DateDiff(Function):
212
- ...
213
- class Extract(Function):
214
- ...
215
- class DatePart(Function):
216
- ...
237
+ def get_pattern(self) -> str:
238
+ def is_field_or_func(name: str) -> bool:
239
+ return re.sub('[()]', '', name).isidentifier()
240
+ if self.dialect != Dialect.SQL_SERVER:
241
+ return ' - '.join(
242
+ p if is_field_or_func(p) else f"'{p}'"
243
+ for p in self.params
244
+ ) # <==== Date subtract
245
+ return super().get_pattern()
246
+
247
+ class Year(Function):
248
+ def get_pattern(self) -> str:
249
+ database_type = {
250
+ Dialect.ORACLE: 'Extract(YEAR FROM {params})',
251
+ Dialect.POSTGRESQL: "Date_Part('year', {params})",
252
+ }
253
+ if self.dialect in database_type:
254
+ return database_type[self.dialect]
255
+ return super().get_pattern()
256
+
217
257
  class Current_Date(Function):
218
- ...
258
+ def get_pattern(self) -> str:
259
+ database_type = {
260
+ Dialect.ORACLE: SQL_CONST_SYSDATE,
261
+ Dialect.POSTGRESQL: SQL_CONST_CURR_DATE,
262
+ Dialect.SQL_SERVER: 'getDate()'
263
+ }
264
+ if self.dialect in database_type:
265
+ return database_type[self.dialect]
266
+ return super().get_pattern()
267
+ # --------------------------------------------------------
219
268
 
220
269
  class Aggregate:
221
270
  break_lines: bool = True
@@ -230,7 +279,7 @@ class Aggregate:
230
279
  )
231
280
  if keywords and self.break_lines:
232
281
  keywords += '\n\t'
233
- self.pattern = '{}({})' + f' OVER({keywords})'
282
+ self.pattern = self.get_pattern() + f' OVER({keywords})'
234
283
  return self
235
284
 
236
285
 
@@ -329,6 +378,13 @@ def quoted(value) -> str:
329
378
  return str(value)
330
379
 
331
380
 
381
+ class Position(Enum):
382
+ Middle = "LIKE '%{}%'"
383
+ StartWith = "LIKE '{}%'"
384
+ EndsWith = "LIKE '%{}'"
385
+ RegEx = "REGEXP_LIKE('{}')"
386
+
387
+
332
388
  class Where:
333
389
  prefix = ''
334
390
 
@@ -344,8 +400,8 @@ class Where:
344
400
  return cls.__constructor('=', value)
345
401
 
346
402
  @classmethod
347
- def contains(cls, value: str):
348
- return cls(f"LIKE '%{value}%'")
403
+ def contains(cls, content: str, pos: Position = Position.Middle):
404
+ return cls(pos.value.format(content))
349
405
 
350
406
  @classmethod
351
407
  def gt(cls, value):
@@ -1359,12 +1415,3 @@ def detect(text: str) -> Select:
1359
1415
  for query in query_list[1:]:
1360
1416
  result += query
1361
1417
  return result
1362
-
1363
- if __name__ == "__main__":
1364
- OrderBy.sort = SortType.DESC
1365
- query = Select(
1366
- 'order_Detail d',
1367
- customer_id=GroupBy,
1368
- _=Sum('d.unitPrice * d.quantity').As('total', OrderBy)
1369
- )
1370
- print(query)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sql_blocks
3
- Version: 1.25.2
3
+ Version: 1.25.109
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=OnIlTb03DTgK_U8QBnXQtQ-rKrkSuKNj1hjJiHogmYE,47639
3
+ sql_blocks-1.25.109.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
+ sql_blocks-1.25.109.dist-info/METADATA,sha256=TRybMQgmXhlz14FxEV6f4rg0-gTPpveyQi3xEYPdZ1w,13425
5
+ sql_blocks-1.25.109.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
+ sql_blocks-1.25.109.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
+ sql_blocks-1.25.109.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
2
- sql_blocks/sql_blocks.py,sha256=R2xZsaKRd600rsZf0lzyXITALpZ3ZXBmwOADNpX1qUA,45798
3
- sql_blocks-1.25.2.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
- sql_blocks-1.25.2.dist-info/METADATA,sha256=NKLAHw43avYevBxxWhKBts8tOB2AaKETMp08dCoSAzQ,13423
5
- sql_blocks-1.25.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
- sql_blocks-1.25.2.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
- sql_blocks-1.25.2.dist-info/RECORD,,