velocity-python 0.0.131__tar.gz → 0.0.132__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.
Potentially problematic release.
This version of velocity-python might be problematic. Click here for more details.
- {velocity_python-0.0.131 → velocity_python-0.0.132}/PKG-INFO +1 -1
- {velocity_python-0.0.131 → velocity_python-0.0.132}/pyproject.toml +1 -1
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/__init__.py +1 -1
- velocity_python-0.0.132/src/velocity/db/servers/base/__init__.py +9 -0
- velocity_python-0.0.132/src/velocity/db/servers/base/initializer.py +69 -0
- velocity_python-0.0.132/src/velocity/db/servers/base/operators.py +98 -0
- velocity_python-0.0.132/src/velocity/db/servers/base/sql.py +503 -0
- velocity_python-0.0.132/src/velocity/db/servers/base/types.py +135 -0
- velocity_python-0.0.132/src/velocity/db/servers/mysql/__init__.py +64 -0
- velocity_python-0.0.132/src/velocity/db/servers/mysql/operators.py +54 -0
- velocity_python-0.0.131/src/velocity/db/servers/mysql_reserved.py → velocity_python-0.0.132/src/velocity/db/servers/mysql/reserved.py +2 -14
- velocity_python-0.0.132/src/velocity/db/servers/mysql/sql.py +569 -0
- {velocity_python-0.0.131/src/velocity/db/servers/postgres → velocity_python-0.0.132/src/velocity/db/servers/mysql}/types.py +31 -33
- velocity_python-0.0.132/src/velocity/db/servers/postgres/__init__.py +57 -0
- velocity_python-0.0.132/src/velocity/db/servers/postgres/operators.py +57 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/servers/postgres/sql.py +4 -3
- velocity_python-0.0.132/src/velocity/db/servers/postgres/types.py +195 -0
- velocity_python-0.0.132/src/velocity/db/servers/sqlite/__init__.py +52 -0
- velocity_python-0.0.132/src/velocity/db/servers/sqlite/operators.py +52 -0
- velocity_python-0.0.132/src/velocity/db/servers/sqlite/reserved.py +20 -0
- velocity_python-0.0.132/src/velocity/db/servers/sqlite/sql.py +530 -0
- velocity_python-0.0.132/src/velocity/db/servers/sqlite/types.py +92 -0
- velocity_python-0.0.132/src/velocity/db/servers/sqlserver/__init__.py +64 -0
- velocity_python-0.0.132/src/velocity/db/servers/sqlserver/operators.py +47 -0
- velocity_python-0.0.132/src/velocity/db/servers/sqlserver/reserved.py +32 -0
- velocity_python-0.0.132/src/velocity/db/servers/sqlserver/sql.py +625 -0
- velocity_python-0.0.132/src/velocity/db/servers/sqlserver/types.py +114 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity_python.egg-info/PKG-INFO +1 -1
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity_python.egg-info/SOURCES.txt +21 -6
- velocity_python-0.0.132/tests/test_postgres_unchanged.py +81 -0
- velocity_python-0.0.131/src/velocity/db/servers/mysql.py +0 -640
- velocity_python-0.0.131/src/velocity/db/servers/postgres/__init__.py +0 -17
- velocity_python-0.0.131/src/velocity/db/servers/postgres/operators.py +0 -23
- velocity_python-0.0.131/src/velocity/db/servers/sqlite.py +0 -968
- velocity_python-0.0.131/src/velocity/db/servers/sqlite_reserved.py +0 -208
- velocity_python-0.0.131/src/velocity/db/servers/sqlserver.py +0 -921
- velocity_python-0.0.131/src/velocity/db/servers/sqlserver_reserved.py +0 -314
- {velocity_python-0.0.131 → velocity_python-0.0.132}/LICENSE +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/README.md +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/setup.cfg +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/app/__init__.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/app/invoices.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/app/orders.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/app/payments.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/app/purchase_orders.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/aws/__init__.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/aws/amplify.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/aws/handlers/__init__.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/aws/handlers/base_handler.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/aws/handlers/context.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/aws/handlers/exceptions.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/aws/handlers/lambda_handler.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/aws/handlers/mixins/__init__.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/aws/handlers/mixins/activity_tracker.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/aws/handlers/mixins/error_handler.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/aws/handlers/mixins/legacy_mixin.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/aws/handlers/mixins/standard_mixin.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/aws/handlers/response.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/aws/handlers/sqs_handler.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/__init__.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/core/__init__.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/core/column.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/core/database.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/core/decorators.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/core/engine.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/core/result.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/core/row.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/core/sequence.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/core/table.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/core/transaction.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/exceptions.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/servers/__init__.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/servers/postgres/reserved.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/servers/tablehelper.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/db/utils.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/misc/__init__.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/misc/conv/__init__.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/misc/conv/iconv.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/misc/conv/oconv.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/misc/db.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/misc/export.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/misc/format.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/misc/mail.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/misc/merge.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/misc/timer.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity/misc/tools.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity_python.egg-info/dependency_links.txt +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity_python.egg-info/requires.txt +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/src/velocity_python.egg-info/top_level.txt +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_cursor_rowcount_fix.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_db.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_db_utils.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_email_processing.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_fix.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_format.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_iconv.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_lambda_handler_json_serialization.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_merge.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_oconv.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_original_error.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_payment_profile_sorting.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_postgres.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_process_error_robustness.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_response.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_result_caching.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_result_sql_aware.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_row_get_missing_column.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_spreadsheet_functions.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_sql_builder.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_tablehelper.py +0 -0
- {velocity_python-0.0.131 → velocity_python-0.0.132}/tests/test_timer.py +0 -0
|
@@ -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
|