velocity-python 0.0.131__py3-none-any.whl → 0.0.132__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.

Potentially problematic release.


This version of velocity-python might be problematic. Click here for more details.

Files changed (35) hide show
  1. velocity/__init__.py +1 -1
  2. velocity/db/servers/base/__init__.py +9 -0
  3. velocity/db/servers/base/initializer.py +69 -0
  4. velocity/db/servers/base/operators.py +98 -0
  5. velocity/db/servers/base/sql.py +503 -0
  6. velocity/db/servers/base/types.py +135 -0
  7. velocity/db/servers/mysql/__init__.py +64 -0
  8. velocity/db/servers/mysql/operators.py +54 -0
  9. velocity/db/servers/{mysql_reserved.py → mysql/reserved.py} +2 -14
  10. velocity/db/servers/mysql/sql.py +569 -0
  11. velocity/db/servers/mysql/types.py +107 -0
  12. velocity/db/servers/postgres/__init__.py +40 -0
  13. velocity/db/servers/postgres/operators.py +34 -0
  14. velocity/db/servers/postgres/sql.py +4 -3
  15. velocity/db/servers/postgres/types.py +88 -2
  16. velocity/db/servers/sqlite/__init__.py +52 -0
  17. velocity/db/servers/sqlite/operators.py +52 -0
  18. velocity/db/servers/sqlite/reserved.py +20 -0
  19. velocity/db/servers/sqlite/sql.py +530 -0
  20. velocity/db/servers/sqlite/types.py +92 -0
  21. velocity/db/servers/sqlserver/__init__.py +64 -0
  22. velocity/db/servers/sqlserver/operators.py +47 -0
  23. velocity/db/servers/sqlserver/reserved.py +32 -0
  24. velocity/db/servers/sqlserver/sql.py +625 -0
  25. velocity/db/servers/sqlserver/types.py +114 -0
  26. {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/METADATA +1 -1
  27. {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/RECORD +30 -16
  28. velocity/db/servers/mysql.py +0 -640
  29. velocity/db/servers/sqlite.py +0 -968
  30. velocity/db/servers/sqlite_reserved.py +0 -208
  31. velocity/db/servers/sqlserver.py +0 -921
  32. velocity/db/servers/sqlserver_reserved.py +0 -314
  33. {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/WHEEL +0 -0
  34. {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/licenses/LICENSE +0 -0
  35. {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/top_level.txt +0 -0
velocity/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = version = "0.0.131"
1
+ __version__ = version = "0.0.132"
2
2
 
3
3
  from . import aws
4
4
  from . import db
@@ -0,0 +1,9 @@
1
+ """
2
+ Base abstract classes for database server implementations.
3
+ """
4
+ from .sql import BaseSQLDialect
5
+ from .types import BaseTypes
6
+ from .operators import BaseOperators
7
+ from .initializer import BaseInitializer
8
+
9
+ __all__ = ["BaseSQLDialect", "BaseTypes", "BaseOperators", "BaseInitializer"]
@@ -0,0 +1,69 @@
1
+ """
2
+ Abstract base class for database initialization.
3
+ """
4
+ from abc import ABC, abstractmethod
5
+ from typing import Any, Dict, Optional
6
+ from velocity.db.core import engine
7
+
8
+
9
+ class BaseInitializer(ABC):
10
+ """
11
+ Abstract base class for database connection initialization.
12
+
13
+ Each database implementation should provide a concrete implementation
14
+ of the initialize method to set up database connections properly.
15
+ """
16
+
17
+ @staticmethod
18
+ @abstractmethod
19
+ def initialize(config: Optional[Dict[str, Any]] = None, **kwargs) -> engine.Engine:
20
+ """
21
+ Initialize a database engine with the appropriate driver and configuration.
22
+
23
+ Args:
24
+ config: Configuration dictionary (can be None)
25
+ **kwargs: Additional configuration parameters
26
+
27
+ Returns:
28
+ Configured Engine instance
29
+
30
+ Raises:
31
+ ImportError: If required database driver is not available
32
+ ValueError: If configuration is invalid
33
+ """
34
+ pass
35
+
36
+ @staticmethod
37
+ def _merge_config(base_config: Dict[str, Any], config: Optional[Dict[str, Any]], **kwargs) -> Dict[str, Any]:
38
+ """
39
+ Helper method to merge configuration from multiple sources.
40
+
41
+ Args:
42
+ base_config: Base configuration (e.g., from environment)
43
+ config: User-provided configuration
44
+ **kwargs: Additional keyword arguments
45
+
46
+ Returns:
47
+ Merged configuration dictionary
48
+ """
49
+ final_config = base_config.copy()
50
+ if config:
51
+ final_config.update(config)
52
+ final_config.update(kwargs)
53
+ return final_config
54
+
55
+ @staticmethod
56
+ def _validate_required_config(config: Dict[str, Any], required_keys: list[str]) -> None:
57
+ """
58
+ Validate that required configuration keys are present.
59
+
60
+ Args:
61
+ config: Configuration to validate
62
+ required_keys: List of required configuration keys
63
+
64
+ Raises:
65
+ ValueError: If required keys are missing
66
+ """
67
+ missing_keys = [key for key in required_keys if key not in config]
68
+ if missing_keys:
69
+ raise ValueError(f"Missing required configuration keys: {missing_keys}")
@@ -0,0 +1,98 @@
1
+ """
2
+ Abstract base class for database operator mapping implementations.
3
+ """
4
+ from abc import ABC, abstractmethod
5
+ from typing import Dict
6
+
7
+
8
+ class BaseOperators(ABC):
9
+ """
10
+ Abstract base class that defines the interface for database operator mappings.
11
+
12
+ Each database implementation should provide concrete implementations of operator
13
+ mappings to handle conversion between Velocity.DB operators and SQL operators.
14
+ """
15
+
16
+ @classmethod
17
+ @abstractmethod
18
+ def get_operators(cls) -> Dict[str, str]:
19
+ """
20
+ Returns a dictionary mapping Velocity.DB operators to SQL operators.
21
+
22
+ This method should return a complete mapping of all operators supported
23
+ by this database implementation.
24
+
25
+ Returns:
26
+ Dictionary mapping operator symbols to SQL operators
27
+
28
+ Examples:
29
+ {
30
+ "=": "=",
31
+ "!=": "<>",
32
+ "<>": "<>",
33
+ "%": "LIKE",
34
+ "!%": "NOT LIKE",
35
+ "%%": "ILIKE", # PostgreSQL case-insensitive
36
+ "!%%": "NOT ILIKE",
37
+ "><": "BETWEEN",
38
+ "!><": "NOT BETWEEN",
39
+ # ... etc
40
+ }
41
+ """
42
+ pass
43
+
44
+ @classmethod
45
+ def get_base_operators(cls) -> Dict[str, str]:
46
+ """
47
+ Returns common operators supported by most databases.
48
+ Subclasses can use this as a starting point and override specific operators.
49
+
50
+ Returns:
51
+ Dictionary of common SQL operators
52
+ """
53
+ return {
54
+ "=": "=",
55
+ "==": "=",
56
+ "!=": "<>",
57
+ "<>": "<>",
58
+ "!": "<>",
59
+ "<": "<",
60
+ ">": ">",
61
+ "<=": "<=",
62
+ ">=": ">=",
63
+ "%": "LIKE",
64
+ "!%": "NOT LIKE",
65
+ "><": "BETWEEN",
66
+ "!><": "NOT BETWEEN",
67
+ ">!<": "NOT BETWEEN",
68
+ }
69
+
70
+ @classmethod
71
+ def supports_case_insensitive_like(cls) -> bool:
72
+ """
73
+ Returns True if this database supports case-insensitive LIKE operations.
74
+
75
+ Returns:
76
+ True if database supports ILIKE or similar
77
+ """
78
+ return False
79
+
80
+ @classmethod
81
+ def supports_regex(cls) -> bool:
82
+ """
83
+ Returns True if this database supports regular expressions.
84
+
85
+ Returns:
86
+ True if database supports regex operators
87
+ """
88
+ return False
89
+
90
+ @classmethod
91
+ def get_regex_operators(cls) -> Dict[str, str]:
92
+ """
93
+ Returns regex operators if supported by this database.
94
+
95
+ Returns:
96
+ Dictionary of regex operators or empty dict if not supported
97
+ """
98
+ return {}
@@ -0,0 +1,503 @@
1
+ """
2
+ Abstract base class for SQL dialect implementations.
3
+ """
4
+ from abc import ABC, abstractmethod
5
+ from typing import Any, Dict, List, Optional, Tuple, Union
6
+ from collections.abc import Mapping, Sequence
7
+
8
+
9
+ class BaseSQLDialect(ABC):
10
+ """
11
+ Abstract base class that defines the interface all database SQL dialects must implement.
12
+
13
+ This class ensures consistency across all database implementations and makes it clear
14
+ what methods each database dialect needs to provide.
15
+ """
16
+
17
+ # Database server identifier - must be set by subclasses
18
+ server: str = ""
19
+
20
+ # Column metadata identifiers - database specific
21
+ type_column_identifier: str = ""
22
+ is_nullable: str = ""
23
+
24
+ # Default schema name for this database
25
+ default_schema: str = ""
26
+
27
+ # Error code classifications - must be set by subclasses
28
+ ApplicationErrorCodes: List[str] = []
29
+ DatabaseMissingErrorCodes: List[str] = []
30
+ TableMissingErrorCodes: List[str] = []
31
+ ColumnMissingErrorCodes: List[str] = []
32
+ ForeignKeyMissingErrorCodes: List[str] = []
33
+ ConnectionErrorCodes: List[str] = []
34
+ DuplicateKeyErrorCodes: List[str] = []
35
+ RetryTransactionCodes: List[str] = []
36
+ TruncationErrorCodes: List[str] = []
37
+ LockTimeoutErrorCodes: List[str] = []
38
+ DatabaseObjectExistsErrorCodes: List[str] = []
39
+ DataIntegrityErrorCodes: List[str] = []
40
+
41
+ @classmethod
42
+ @abstractmethod
43
+ def get_error(cls, e: Exception) -> Optional[str]:
44
+ """
45
+ Extract error information from database exception.
46
+
47
+ Args:
48
+ e: Database exception
49
+
50
+ Returns:
51
+ Error code or message, or None if not applicable
52
+ """
53
+ pass
54
+
55
+ # Core CRUD Operations
56
+ @classmethod
57
+ @abstractmethod
58
+ def select(
59
+ cls,
60
+ tx: Any,
61
+ columns: Optional[Union[str, List[str]]] = None,
62
+ table: Optional[str] = None,
63
+ where: Optional[Union[str, Dict, List]] = None,
64
+ orderby: Optional[Union[str, List, Dict]] = None,
65
+ groupby: Optional[Union[str, List]] = None,
66
+ having: Optional[Union[str, Dict, List]] = None,
67
+ start: Optional[int] = None,
68
+ qty: Optional[int] = None,
69
+ lock: Optional[bool] = None,
70
+ skip_locked: Optional[bool] = None,
71
+ ) -> Tuple[str, List[Any]]:
72
+ """
73
+ Generate a SELECT statement.
74
+
75
+ Returns:
76
+ Tuple of (sql_string, parameters)
77
+ """
78
+ pass
79
+
80
+ @classmethod
81
+ @abstractmethod
82
+ def insert(cls, table: str, data: Dict[str, Any]) -> Tuple[str, List[Any]]:
83
+ """
84
+ Generate an INSERT statement.
85
+
86
+ Args:
87
+ table: Table name
88
+ data: Dictionary of column names to values
89
+
90
+ Returns:
91
+ Tuple of (sql_string, parameters)
92
+ """
93
+ pass
94
+
95
+ @classmethod
96
+ @abstractmethod
97
+ def update(
98
+ cls,
99
+ tx: Any,
100
+ table: str,
101
+ data: Dict[str, Any],
102
+ where: Optional[Union[str, Dict, List]] = None,
103
+ pk: Optional[Dict[str, Any]] = None,
104
+ excluded: bool = False
105
+ ) -> Tuple[str, List[Any]]:
106
+ """
107
+ Generate an UPDATE statement.
108
+
109
+ Args:
110
+ tx: Database transaction
111
+ table: Table name
112
+ data: Dictionary of columns to update
113
+ where: WHERE clause conditions
114
+ pk: Primary key conditions to merge with where
115
+ excluded: If True, creates EXCLUDED.col expressions for upserts
116
+
117
+ Returns:
118
+ Tuple of (sql_string, parameters)
119
+ """
120
+ pass
121
+
122
+ @classmethod
123
+ @abstractmethod
124
+ def delete(cls, tx: Any, table: str, where: Union[str, Dict, List]) -> Tuple[str, List[Any]]:
125
+ """
126
+ Generate a DELETE statement.
127
+
128
+ Args:
129
+ tx: Database transaction
130
+ table: Table name
131
+ where: WHERE clause conditions
132
+
133
+ Returns:
134
+ Tuple of (sql_string, parameters)
135
+ """
136
+ pass
137
+
138
+ @classmethod
139
+ @abstractmethod
140
+ def merge(
141
+ cls,
142
+ tx: Any,
143
+ table: str,
144
+ data: Dict[str, Any],
145
+ pk: Dict[str, Any],
146
+ on_conflict_do_nothing: bool,
147
+ on_conflict_update: bool
148
+ ) -> Tuple[str, List[Any]]:
149
+ """
150
+ Generate an UPSERT/MERGE statement.
151
+
152
+ Args:
153
+ tx: Database transaction
154
+ table: Table name
155
+ data: Data to insert/update
156
+ pk: Primary key columns
157
+ on_conflict_do_nothing: If True, ignore conflicts
158
+ on_conflict_update: If True, update on conflicts
159
+
160
+ Returns:
161
+ Tuple of (sql_string, parameters)
162
+ """
163
+ pass
164
+
165
+ # Database Metadata Operations
166
+ @classmethod
167
+ @abstractmethod
168
+ def version(cls) -> str:
169
+ """Get database version query."""
170
+ pass
171
+
172
+ @classmethod
173
+ @abstractmethod
174
+ def timestamp(cls) -> str:
175
+ """Get current timestamp query."""
176
+ pass
177
+
178
+ @classmethod
179
+ @abstractmethod
180
+ def user(cls) -> str:
181
+ """Get current user query."""
182
+ pass
183
+
184
+ @classmethod
185
+ @abstractmethod
186
+ def databases(cls) -> str:
187
+ """Get list of databases query."""
188
+ pass
189
+
190
+ @classmethod
191
+ @abstractmethod
192
+ def schemas(cls) -> str:
193
+ """Get list of schemas query."""
194
+ pass
195
+
196
+ @classmethod
197
+ @abstractmethod
198
+ def current_schema(cls) -> str:
199
+ """Get current schema query."""
200
+ pass
201
+
202
+ @classmethod
203
+ @abstractmethod
204
+ def current_database(cls) -> str:
205
+ """Get current database query."""
206
+ pass
207
+
208
+ @classmethod
209
+ @abstractmethod
210
+ def tables(cls, system: bool = False) -> str:
211
+ """
212
+ Get list of tables query.
213
+
214
+ Args:
215
+ system: Include system tables
216
+ """
217
+ pass
218
+
219
+ @classmethod
220
+ @abstractmethod
221
+ def views(cls, system: bool = False) -> str:
222
+ """
223
+ Get list of views query.
224
+
225
+ Args:
226
+ system: Include system views
227
+ """
228
+ pass
229
+
230
+ # Database Structure Operations
231
+ @classmethod
232
+ @abstractmethod
233
+ def create_database(cls, name: str) -> str:
234
+ """Generate CREATE DATABASE statement."""
235
+ pass
236
+
237
+ @classmethod
238
+ @abstractmethod
239
+ def drop_database(cls, name: str) -> str:
240
+ """Generate DROP DATABASE statement."""
241
+ pass
242
+
243
+ @classmethod
244
+ @abstractmethod
245
+ def create_table(cls, name: str, columns: Dict[str, Any] = None, drop: bool = False) -> str:
246
+ """
247
+ Generate CREATE TABLE statement.
248
+
249
+ Args:
250
+ name: Table name
251
+ columns: Column definitions
252
+ drop: Drop table if exists first
253
+ """
254
+ pass
255
+
256
+ @classmethod
257
+ @abstractmethod
258
+ def drop_table(cls, name: str) -> str:
259
+ """Generate DROP TABLE statement."""
260
+ pass
261
+
262
+ @classmethod
263
+ @abstractmethod
264
+ def truncate(cls, table: str) -> str:
265
+ """Generate TRUNCATE statement."""
266
+ pass
267
+
268
+ # Column Operations
269
+ @classmethod
270
+ @abstractmethod
271
+ def columns(cls, name: str) -> str:
272
+ """Get table columns query."""
273
+ pass
274
+
275
+ @classmethod
276
+ @abstractmethod
277
+ def column_info(cls, table: str, name: str) -> str:
278
+ """Get column information query."""
279
+ pass
280
+
281
+ @classmethod
282
+ @abstractmethod
283
+ def drop_column(cls, table: str, name: str, cascade: bool = True) -> str:
284
+ """Generate DROP COLUMN statement."""
285
+ pass
286
+
287
+ @classmethod
288
+ @abstractmethod
289
+ def alter_add(cls, table: str, columns: Dict[str, Any], null_allowed: bool = True) -> str:
290
+ """Generate ALTER TABLE ADD COLUMN statement."""
291
+ pass
292
+
293
+ @classmethod
294
+ @abstractmethod
295
+ def alter_drop(cls, table: str, columns: List[str]) -> str:
296
+ """Generate ALTER TABLE DROP COLUMN statement."""
297
+ pass
298
+
299
+ @classmethod
300
+ @abstractmethod
301
+ def alter_column_by_type(cls, table: str, column: str, value: str, nullable: bool = True) -> str:
302
+ """Generate ALTER COLUMN statement by type."""
303
+ pass
304
+
305
+ @classmethod
306
+ @abstractmethod
307
+ def alter_column_by_sql(cls, table: str, column: str, value: str) -> str:
308
+ """Generate ALTER COLUMN statement by SQL."""
309
+ pass
310
+
311
+ @classmethod
312
+ @abstractmethod
313
+ def rename_column(cls, table: str, orig: str, new: str) -> str:
314
+ """Generate RENAME COLUMN statement."""
315
+ pass
316
+
317
+ @classmethod
318
+ @abstractmethod
319
+ def rename_table(cls, table: str, new: str) -> str:
320
+ """Generate RENAME TABLE statement."""
321
+ pass
322
+
323
+ # Key Operations
324
+ @classmethod
325
+ @abstractmethod
326
+ def primary_keys(cls, table: str) -> str:
327
+ """Get primary key columns query."""
328
+ pass
329
+
330
+ @classmethod
331
+ @abstractmethod
332
+ def foreign_key_info(
333
+ cls,
334
+ table: Optional[str] = None,
335
+ column: Optional[str] = None,
336
+ schema: Optional[str] = None
337
+ ) -> str:
338
+ """Get foreign key information query."""
339
+ pass
340
+
341
+ @classmethod
342
+ @abstractmethod
343
+ def create_foreign_key(
344
+ cls,
345
+ table: str,
346
+ columns: List[str],
347
+ key_to_table: str,
348
+ key_to_columns: List[str],
349
+ name: Optional[str] = None,
350
+ schema: Optional[str] = None,
351
+ ) -> str:
352
+ """Generate CREATE FOREIGN KEY statement."""
353
+ pass
354
+
355
+ @classmethod
356
+ @abstractmethod
357
+ def drop_foreign_key(
358
+ cls,
359
+ table: str,
360
+ columns: List[str],
361
+ key_to_table: Optional[str] = None,
362
+ key_to_columns: Optional[List[str]] = None,
363
+ name: Optional[str] = None,
364
+ schema: Optional[str] = None,
365
+ ) -> str:
366
+ """Generate DROP FOREIGN KEY statement."""
367
+ pass
368
+
369
+ # Index Operations
370
+ @classmethod
371
+ @abstractmethod
372
+ def create_index(
373
+ cls,
374
+ tx: Any,
375
+ table: Optional[str] = None,
376
+ columns: Optional[List[str]] = None,
377
+ unique: bool = False,
378
+ direction: Optional[str] = None,
379
+ where: Optional[str] = None,
380
+ name: Optional[str] = None,
381
+ schema: Optional[str] = None,
382
+ trigram: Optional[bool] = None,
383
+ lower: Optional[bool] = None,
384
+ ) -> str:
385
+ """Generate CREATE INDEX statement."""
386
+ pass
387
+
388
+ @classmethod
389
+ @abstractmethod
390
+ def drop_index(
391
+ cls,
392
+ table: Optional[str] = None,
393
+ columns: Optional[List[str]] = None,
394
+ name: Optional[str] = None,
395
+ schema: Optional[str] = None,
396
+ trigram: Optional[bool] = None,
397
+ ) -> str:
398
+ """Generate DROP INDEX statement."""
399
+ pass
400
+
401
+ @classmethod
402
+ @abstractmethod
403
+ def indexes(cls, table: str) -> str:
404
+ """Get table indexes query."""
405
+ pass
406
+
407
+ # Transaction Operations
408
+ @classmethod
409
+ @abstractmethod
410
+ def create_savepoint(cls, sp: str) -> str:
411
+ """Generate SAVEPOINT statement."""
412
+ pass
413
+
414
+ @classmethod
415
+ @abstractmethod
416
+ def release_savepoint(cls, sp: str) -> str:
417
+ """Generate RELEASE SAVEPOINT statement."""
418
+ pass
419
+
420
+ @classmethod
421
+ @abstractmethod
422
+ def rollback_savepoint(cls, sp: str) -> str:
423
+ """Generate ROLLBACK TO SAVEPOINT statement."""
424
+ pass
425
+
426
+ # View Operations
427
+ @classmethod
428
+ @abstractmethod
429
+ def create_view(cls, name: str, query: str, temp: bool = False, silent: bool = True) -> str:
430
+ """Generate CREATE VIEW statement."""
431
+ pass
432
+
433
+ @classmethod
434
+ @abstractmethod
435
+ def drop_view(cls, name: str, silent: bool = True) -> str:
436
+ """Generate DROP VIEW statement."""
437
+ pass
438
+
439
+ # Sequence/Identity Operations
440
+ @classmethod
441
+ @abstractmethod
442
+ def last_id(cls, table: str) -> str:
443
+ """Get last inserted ID query."""
444
+ pass
445
+
446
+ @classmethod
447
+ @abstractmethod
448
+ def current_id(cls, table: str) -> str:
449
+ """Get current sequence value query."""
450
+ pass
451
+
452
+ @classmethod
453
+ @abstractmethod
454
+ def set_id(cls, table: str, start: int) -> str:
455
+ """Generate set sequence value statement."""
456
+ pass
457
+
458
+ @classmethod
459
+ @abstractmethod
460
+ def set_sequence(cls, table: str, next_value: int) -> str:
461
+ """Generate set sequence next value statement."""
462
+ pass
463
+
464
+ # Utility Operations
465
+ @classmethod
466
+ @abstractmethod
467
+ def massage_data(cls, data: Dict[str, Any]) -> Dict[str, Any]:
468
+ """
469
+ Massage data before insert/update operations.
470
+ Database-specific data transformations.
471
+ """
472
+ pass
473
+
474
+ @classmethod
475
+ @abstractmethod
476
+ def alter_trigger(cls, table: str, state: str = "ENABLE", name: str = "USER") -> str:
477
+ """Generate ALTER TRIGGER statement."""
478
+ pass
479
+
480
+ @classmethod
481
+ @abstractmethod
482
+ def missing(
483
+ cls,
484
+ tx: Any,
485
+ table: str,
486
+ list_values: List[Any],
487
+ column: str = "SYS_ID",
488
+ where: Optional[Union[str, Dict, List]] = None,
489
+ ) -> Tuple[str, List[Any]]:
490
+ """
491
+ Generate query to find missing values from a list.
492
+
493
+ Args:
494
+ tx: Database transaction
495
+ table: Table name
496
+ list_values: List of values to check
497
+ column: Column to check against
498
+ where: Additional WHERE conditions
499
+
500
+ Returns:
501
+ Tuple of (sql_string, parameters)
502
+ """
503
+ pass