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.
- velocity/__init__.py +1 -1
- velocity/db/servers/base/__init__.py +9 -0
- velocity/db/servers/base/initializer.py +69 -0
- velocity/db/servers/base/operators.py +98 -0
- velocity/db/servers/base/sql.py +503 -0
- velocity/db/servers/base/types.py +135 -0
- velocity/db/servers/mysql/__init__.py +64 -0
- velocity/db/servers/mysql/operators.py +54 -0
- velocity/db/servers/{mysql_reserved.py → mysql/reserved.py} +2 -14
- velocity/db/servers/mysql/sql.py +569 -0
- velocity/db/servers/mysql/types.py +107 -0
- velocity/db/servers/postgres/__init__.py +40 -0
- velocity/db/servers/postgres/operators.py +34 -0
- velocity/db/servers/postgres/sql.py +4 -3
- velocity/db/servers/postgres/types.py +88 -2
- velocity/db/servers/sqlite/__init__.py +52 -0
- velocity/db/servers/sqlite/operators.py +52 -0
- velocity/db/servers/sqlite/reserved.py +20 -0
- velocity/db/servers/sqlite/sql.py +530 -0
- velocity/db/servers/sqlite/types.py +92 -0
- velocity/db/servers/sqlserver/__init__.py +64 -0
- velocity/db/servers/sqlserver/operators.py +47 -0
- velocity/db/servers/sqlserver/reserved.py +32 -0
- velocity/db/servers/sqlserver/sql.py +625 -0
- velocity/db/servers/sqlserver/types.py +114 -0
- {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/METADATA +1 -1
- {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/RECORD +30 -16
- velocity/db/servers/mysql.py +0 -640
- velocity/db/servers/sqlite.py +0 -968
- velocity/db/servers/sqlite_reserved.py +0 -208
- velocity/db/servers/sqlserver.py +0 -921
- velocity/db/servers/sqlserver_reserved.py +0 -314
- {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/WHEEL +0 -0
- {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/licenses/LICENSE +0 -0
- {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/top_level.txt +0 -0
|
@@ -1,10 +1,50 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import psycopg2
|
|
3
3
|
from .sql import SQL
|
|
4
|
+
from ..base.initializer import BaseInitializer
|
|
4
5
|
from velocity.db.core import engine
|
|
5
6
|
|
|
6
7
|
|
|
8
|
+
class PostgreSQLInitializer(BaseInitializer):
|
|
9
|
+
"""PostgreSQL database initializer."""
|
|
10
|
+
|
|
11
|
+
@staticmethod
|
|
12
|
+
def initialize(config=None, **kwargs):
|
|
13
|
+
"""
|
|
14
|
+
Initialize PostgreSQL engine with psycopg2 driver.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
config: Configuration dictionary
|
|
18
|
+
**kwargs: Additional configuration parameters
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
Configured Engine instance
|
|
22
|
+
"""
|
|
23
|
+
# Base configuration from environment
|
|
24
|
+
base_config = {
|
|
25
|
+
"database": os.environ.get("DBDatabase"),
|
|
26
|
+
"host": os.environ.get("DBHost"),
|
|
27
|
+
"port": os.environ.get("DBPort"),
|
|
28
|
+
"user": os.environ.get("DBUser"),
|
|
29
|
+
"password": os.environ.get("DBPassword"),
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# Remove None values
|
|
33
|
+
base_config = {k: v for k, v in base_config.items() if v is not None}
|
|
34
|
+
|
|
35
|
+
# Merge configurations
|
|
36
|
+
final_config = PostgreSQLInitializer._merge_config(base_config, config, **kwargs)
|
|
37
|
+
|
|
38
|
+
# Validate required configuration
|
|
39
|
+
required_keys = ["database", "host", "user", "password"]
|
|
40
|
+
PostgreSQLInitializer._validate_required_config(final_config, required_keys)
|
|
41
|
+
|
|
42
|
+
return engine.Engine(psycopg2, final_config, SQL)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# Maintain backward compatibility
|
|
7
46
|
def initialize(config=None, **kwargs):
|
|
47
|
+
"""Backward compatible initialization function - matches original behavior exactly."""
|
|
8
48
|
konfig = {
|
|
9
49
|
"database": os.environ["DBDatabase"],
|
|
10
50
|
"host": os.environ["DBHost"],
|
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
from ..base.operators import BaseOperators
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PostgreSQLOperators(BaseOperators):
|
|
5
|
+
"""
|
|
6
|
+
PostgreSQL-specific operator mappings.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_operators(cls):
|
|
11
|
+
"""Returns PostgreSQL-specific operator mappings."""
|
|
12
|
+
return OPERATORS
|
|
13
|
+
|
|
14
|
+
@classmethod
|
|
15
|
+
def supports_case_insensitive_like(cls):
|
|
16
|
+
"""PostgreSQL supports ILIKE for case-insensitive matching."""
|
|
17
|
+
return True
|
|
18
|
+
|
|
19
|
+
@classmethod
|
|
20
|
+
def supports_regex(cls):
|
|
21
|
+
"""PostgreSQL supports regex operators."""
|
|
22
|
+
return True
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def get_regex_operators(cls):
|
|
26
|
+
"""Returns PostgreSQL regex operators."""
|
|
27
|
+
return {
|
|
28
|
+
"~": "~",
|
|
29
|
+
"!~": "!~",
|
|
30
|
+
"~*": "~*",
|
|
31
|
+
"!~*": "!~*",
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
1
35
|
OPERATORS = {
|
|
2
36
|
"<>": "<>",
|
|
3
37
|
"!=": "<>",
|
|
@@ -4,10 +4,11 @@ import sqlparse
|
|
|
4
4
|
from psycopg2 import sql as psycopg2_sql
|
|
5
5
|
|
|
6
6
|
from velocity.db import exceptions
|
|
7
|
+
from ..base.sql import BaseSQLDialect
|
|
7
8
|
|
|
8
9
|
from .reserved import reserved_words
|
|
9
10
|
from .types import TYPES
|
|
10
|
-
from .operators import OPERATORS
|
|
11
|
+
from .operators import OPERATORS, PostgreSQLOperators
|
|
11
12
|
from ..tablehelper import TableHelper
|
|
12
13
|
from collections.abc import Mapping, Sequence
|
|
13
14
|
|
|
@@ -61,7 +62,7 @@ system_fields = [
|
|
|
61
62
|
]
|
|
62
63
|
|
|
63
64
|
|
|
64
|
-
class SQL:
|
|
65
|
+
class SQL(BaseSQLDialect):
|
|
65
66
|
server = "PostGreSQL"
|
|
66
67
|
type_column_identifier = "data_type"
|
|
67
68
|
is_nullable = "is_nullable"
|
|
@@ -95,7 +96,7 @@ class SQL:
|
|
|
95
96
|
DataIntegrityErrorCodes = ["23503", "23502", "23514", "23P01", "22003"]
|
|
96
97
|
|
|
97
98
|
@classmethod
|
|
98
|
-
def get_error(
|
|
99
|
+
def get_error(cls, e):
|
|
99
100
|
error_code = getattr(e, "pgcode", None)
|
|
100
101
|
error_mesg = getattr(e, "pgerror", None)
|
|
101
102
|
return error_code, error_mesg
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import decimal
|
|
2
2
|
import datetime
|
|
3
|
+
from ..base.types import BaseTypes
|
|
3
4
|
|
|
4
5
|
|
|
5
|
-
class TYPES:
|
|
6
|
+
class TYPES(BaseTypes):
|
|
6
7
|
"""
|
|
7
|
-
|
|
8
|
+
PostgreSQL-specific type mapping implementation.
|
|
8
9
|
"""
|
|
9
10
|
|
|
10
11
|
TEXT = "TEXT"
|
|
@@ -107,3 +108,88 @@ class TYPES:
|
|
|
107
108
|
if v == cls.DATETIME_TZ or v == cls.TIMESTAMP_TZ:
|
|
108
109
|
return datetime.datetime
|
|
109
110
|
raise Exception(f"Unmapped type {v}")
|
|
111
|
+
|
|
112
|
+
@classmethod
|
|
113
|
+
def get_type(cls, v):
|
|
114
|
+
"""
|
|
115
|
+
Returns a suitable SQL type string for a Python value/object.
|
|
116
|
+
"""
|
|
117
|
+
if isinstance(v, str) and v.startswith("@@"):
|
|
118
|
+
# e.g. @@CURRENT_TIMESTAMP => special usage
|
|
119
|
+
return v[2:] or cls.TEXT
|
|
120
|
+
if isinstance(v, str) or v is str:
|
|
121
|
+
return cls.TEXT
|
|
122
|
+
if isinstance(v, bool) or v is bool:
|
|
123
|
+
return cls.BOOLEAN
|
|
124
|
+
if isinstance(v, int) or v is int:
|
|
125
|
+
return cls.BIGINT
|
|
126
|
+
if isinstance(v, float) or v is float:
|
|
127
|
+
return f"{cls.NUMERIC}(19, 6)"
|
|
128
|
+
if isinstance(v, decimal.Decimal) or v is decimal.Decimal:
|
|
129
|
+
return f"{cls.NUMERIC}(19, 6)"
|
|
130
|
+
if isinstance(v, datetime.datetime) or v is datetime.datetime:
|
|
131
|
+
return cls.DATETIME
|
|
132
|
+
if isinstance(v, datetime.date) or v is datetime.date:
|
|
133
|
+
return cls.DATE
|
|
134
|
+
if isinstance(v, datetime.time) or v is datetime.time:
|
|
135
|
+
return cls.TIME
|
|
136
|
+
if isinstance(v, datetime.timedelta) or v is datetime.timedelta:
|
|
137
|
+
return cls.INTERVAL
|
|
138
|
+
if isinstance(v, bytes) or v is bytes:
|
|
139
|
+
return cls.BINARY
|
|
140
|
+
return cls.TEXT
|
|
141
|
+
|
|
142
|
+
@classmethod
|
|
143
|
+
def get_conv(cls, v):
|
|
144
|
+
"""
|
|
145
|
+
Returns a base SQL type for expression usage (e.g. CAST).
|
|
146
|
+
"""
|
|
147
|
+
if isinstance(v, str) and v.startswith("@@"):
|
|
148
|
+
return v[2:] or cls.TEXT
|
|
149
|
+
if isinstance(v, str) or v is str:
|
|
150
|
+
return cls.TEXT
|
|
151
|
+
if isinstance(v, bool) or v is bool:
|
|
152
|
+
return cls.BOOLEAN
|
|
153
|
+
if isinstance(v, int) or v is int:
|
|
154
|
+
return cls.BIGINT
|
|
155
|
+
if isinstance(v, float) or v is float:
|
|
156
|
+
return cls.NUMERIC
|
|
157
|
+
if isinstance(v, decimal.Decimal) or v is decimal.Decimal:
|
|
158
|
+
return cls.NUMERIC
|
|
159
|
+
if isinstance(v, datetime.datetime) or v is datetime.datetime:
|
|
160
|
+
return cls.DATETIME
|
|
161
|
+
if isinstance(v, datetime.date) or v is datetime.date:
|
|
162
|
+
return cls.DATE
|
|
163
|
+
if isinstance(v, datetime.time) or v is datetime.time:
|
|
164
|
+
return cls.TIME
|
|
165
|
+
if isinstance(v, datetime.timedelta) or v is datetime.timedelta:
|
|
166
|
+
return cls.INTERVAL
|
|
167
|
+
if isinstance(v, bytes) or v is bytes:
|
|
168
|
+
return cls.BINARY
|
|
169
|
+
return cls.TEXT
|
|
170
|
+
|
|
171
|
+
@classmethod
|
|
172
|
+
def py_type(cls, v):
|
|
173
|
+
"""
|
|
174
|
+
Returns the Python type that corresponds to an SQL type string.
|
|
175
|
+
"""
|
|
176
|
+
v = str(v).upper()
|
|
177
|
+
if v == cls.INTEGER or v == cls.SMALLINT or v == cls.BIGINT:
|
|
178
|
+
return int
|
|
179
|
+
if v == cls.NUMERIC:
|
|
180
|
+
return decimal.Decimal
|
|
181
|
+
if v == cls.TEXT:
|
|
182
|
+
return str
|
|
183
|
+
if v == cls.BOOLEAN:
|
|
184
|
+
return bool
|
|
185
|
+
if v == cls.DATE:
|
|
186
|
+
return datetime.date
|
|
187
|
+
if v == cls.TIME or v == cls.TIME_TZ:
|
|
188
|
+
return datetime.time
|
|
189
|
+
if v == cls.DATETIME or v == cls.TIMESTAMP:
|
|
190
|
+
return datetime.datetime
|
|
191
|
+
if v == cls.INTERVAL:
|
|
192
|
+
return datetime.timedelta
|
|
193
|
+
if v == cls.DATETIME_TZ or v == cls.TIMESTAMP_TZ:
|
|
194
|
+
return datetime.datetime
|
|
195
|
+
raise Exception(f"Unmapped type {v}")
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sqlite3
|
|
3
|
+
from ..base.initializer import BaseInitializer
|
|
4
|
+
from velocity.db.core import engine
|
|
5
|
+
from .sql import SQL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SQLiteInitializer(BaseInitializer):
|
|
9
|
+
"""SQLite database initializer."""
|
|
10
|
+
|
|
11
|
+
@staticmethod
|
|
12
|
+
def initialize(config=None, **kwargs):
|
|
13
|
+
"""
|
|
14
|
+
Initialize SQLite engine with sqlite3 driver.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
config: Configuration dictionary
|
|
18
|
+
**kwargs: Additional configuration parameters
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
Configured Engine instance
|
|
22
|
+
"""
|
|
23
|
+
# Base configuration - SQLite is simpler
|
|
24
|
+
base_config = {
|
|
25
|
+
"database": os.environ.get("DBDatabase", ":memory:"), # Default to in-memory
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# Remove None values
|
|
29
|
+
base_config = {k: v for k, v in base_config.items() if v is not None}
|
|
30
|
+
|
|
31
|
+
# Set SQLite-specific defaults
|
|
32
|
+
sqlite_defaults = {
|
|
33
|
+
"check_same_thread": False, # Allow usage from different threads
|
|
34
|
+
"timeout": 30.0, # Connection timeout
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# Merge configurations: defaults < env < config < kwargs
|
|
38
|
+
final_config = sqlite_defaults.copy()
|
|
39
|
+
final_config.update(base_config)
|
|
40
|
+
final_config = SQLiteInitializer._merge_config(final_config, config, **kwargs)
|
|
41
|
+
|
|
42
|
+
# Validate required configuration - only database path is required
|
|
43
|
+
required_keys = ["database"]
|
|
44
|
+
SQLiteInitializer._validate_required_config(final_config, required_keys)
|
|
45
|
+
|
|
46
|
+
return engine.Engine(sqlite3, final_config, SQL)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# Maintain backward compatibility
|
|
50
|
+
def initialize(config=None, **kwargs):
|
|
51
|
+
"""Backward compatible initialization function."""
|
|
52
|
+
return SQLiteInitializer.initialize(config, **kwargs)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from ..base.operators import BaseOperators
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SQLiteOperators(BaseOperators):
|
|
5
|
+
"""
|
|
6
|
+
SQLite-specific operator mappings.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_operators(cls):
|
|
11
|
+
"""Returns SQLite-specific operator mappings."""
|
|
12
|
+
return OPERATORS
|
|
13
|
+
|
|
14
|
+
@classmethod
|
|
15
|
+
def supports_case_insensitive_like(cls):
|
|
16
|
+
"""SQLite LIKE is case-insensitive by default."""
|
|
17
|
+
return True # Sort of - depends on the text encoding
|
|
18
|
+
|
|
19
|
+
@classmethod
|
|
20
|
+
def supports_regex(cls):
|
|
21
|
+
"""SQLite supports REGEXP if the REGEXP function is defined."""
|
|
22
|
+
return True # But requires the REGEXP function to be defined
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def get_regex_operators(cls):
|
|
26
|
+
"""Returns SQLite regex operators."""
|
|
27
|
+
return {
|
|
28
|
+
"REGEXP": "REGEXP",
|
|
29
|
+
"GLOB": "GLOB",
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
OPERATORS = {
|
|
34
|
+
"<>": "<>",
|
|
35
|
+
"!=": "<>",
|
|
36
|
+
"!><": "NOT BETWEEN",
|
|
37
|
+
">!<": "NOT BETWEEN",
|
|
38
|
+
"><": "BETWEEN",
|
|
39
|
+
"%%": "LIKE", # SQLite LIKE is case-insensitive by default
|
|
40
|
+
"!%%": "NOT LIKE",
|
|
41
|
+
"==": "=",
|
|
42
|
+
"<=": "<=",
|
|
43
|
+
">=": ">=",
|
|
44
|
+
"<": "<",
|
|
45
|
+
">": ">",
|
|
46
|
+
"%": "LIKE",
|
|
47
|
+
"!%": "NOT LIKE",
|
|
48
|
+
"=": "=",
|
|
49
|
+
"!": "<>",
|
|
50
|
+
"REGEXP": "REGEXP",
|
|
51
|
+
"GLOB": "GLOB",
|
|
52
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
reserved_words = [
|
|
2
|
+
"ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND",
|
|
3
|
+
"AS", "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN",
|
|
4
|
+
"BY", "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN",
|
|
5
|
+
"COMMIT", "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
|
|
6
|
+
"CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE",
|
|
7
|
+
"DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH",
|
|
8
|
+
"ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN",
|
|
9
|
+
"FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING",
|
|
10
|
+
"IF", "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY",
|
|
11
|
+
"INNER", "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL",
|
|
12
|
+
"JOIN", "KEY", "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO",
|
|
13
|
+
"NOT", "NOTNULL", "NULL", "OF", "OFFSET", "ON", "OR", "ORDER",
|
|
14
|
+
"OUTER", "PLAN", "PRAGMA", "PRIMARY", "QUERY", "RAISE", "RECURSIVE",
|
|
15
|
+
"REFERENCES", "REGEXP", "REINDEX", "RELEASE", "RENAME", "REPLACE",
|
|
16
|
+
"RESTRICT", "RIGHT", "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET",
|
|
17
|
+
"TABLE", "TEMP", "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER",
|
|
18
|
+
"UNION", "UNIQUE", "UPDATE", "USING", "VACUUM", "VALUES", "VIEW",
|
|
19
|
+
"VIRTUAL", "WHEN", "WHERE", "WITH", "WITHOUT"
|
|
20
|
+
]
|