sqlalchemy-vertica 0.0.4__tar.gz → 1.0.2__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.
- sqlalchemy_vertica-1.0.2/LICENSE +22 -0
- sqlalchemy_vertica-1.0.2/PKG-INFO +271 -0
- sqlalchemy_vertica-1.0.2/README.rst +225 -0
- sqlalchemy_vertica-1.0.2/pyproject.toml +183 -0
- sqlalchemy_vertica-1.0.2/setup.cfg +4 -0
- sqlalchemy_vertica-1.0.2/setup.py +3 -0
- sqlalchemy_vertica-1.0.2/sqlalchemy_vertica/__init__.py +78 -0
- sqlalchemy_vertica-1.0.2/sqlalchemy_vertica/alembic.py +44 -0
- sqlalchemy_vertica-1.0.2/sqlalchemy_vertica/base.py +864 -0
- sqlalchemy_vertica-1.0.2/sqlalchemy_vertica/dialect_pyodbc.py +16 -0
- sqlalchemy_vertica-1.0.2/sqlalchemy_vertica/dialect_turbodbc.py +36 -0
- sqlalchemy_vertica-1.0.2/sqlalchemy_vertica/dialect_vertica_python.py +65 -0
- sqlalchemy_vertica-1.0.2/sqlalchemy_vertica/dialect_vertica_python_async.py +158 -0
- sqlalchemy_vertica-1.0.2/sqlalchemy_vertica/types.py +216 -0
- sqlalchemy_vertica-1.0.2/sqlalchemy_vertica.egg-info/PKG-INFO +271 -0
- {sqlalchemy-vertica-0.0.4 → sqlalchemy_vertica-1.0.2}/sqlalchemy_vertica.egg-info/SOURCES.txt +14 -2
- sqlalchemy_vertica-1.0.2/sqlalchemy_vertica.egg-info/entry_points.txt +7 -0
- sqlalchemy_vertica-1.0.2/sqlalchemy_vertica.egg-info/requires.txt +25 -0
- sqlalchemy_vertica-1.0.2/tests/test_alembic.py +97 -0
- sqlalchemy_vertica-1.0.2/tests/test_async.py +192 -0
- sqlalchemy_vertica-1.0.2/tests/test_compiler.py +100 -0
- sqlalchemy_vertica-1.0.2/tests/test_dialect.py +143 -0
- sqlalchemy_vertica-1.0.2/tests/test_drivers.py +60 -0
- sqlalchemy_vertica-1.0.2/tests/test_reflection.py +292 -0
- sqlalchemy_vertica-1.0.2/tests/test_types.py +184 -0
- sqlalchemy-vertica-0.0.4/PKG-INFO +0 -54
- sqlalchemy-vertica-0.0.4/README.rst +0 -41
- sqlalchemy-vertica-0.0.4/setup.cfg +0 -7
- sqlalchemy-vertica-0.0.4/setup.py +0 -42
- sqlalchemy-vertica-0.0.4/sqlalchemy_vertica/__init__.py +0 -0
- sqlalchemy-vertica-0.0.4/sqlalchemy_vertica/base.py +0 -373
- sqlalchemy-vertica-0.0.4/sqlalchemy_vertica/dialect_pyodbc.py +0 -10
- sqlalchemy-vertica-0.0.4/sqlalchemy_vertica/dialect_vertica_python.py +0 -13
- sqlalchemy-vertica-0.0.4/sqlalchemy_vertica.egg-info/PKG-INFO +0 -54
- sqlalchemy-vertica-0.0.4/sqlalchemy_vertica.egg-info/entry_points.txt +0 -4
- sqlalchemy-vertica-0.0.4/sqlalchemy_vertica.egg-info/requires.txt +0 -8
- {sqlalchemy-vertica-0.0.4 → sqlalchemy_vertica-1.0.2}/sqlalchemy_vertica.egg-info/dependency_links.txt +0 -0
- {sqlalchemy-vertica-0.0.4 → sqlalchemy_vertica-1.0.2}/sqlalchemy_vertica.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2017 StartApp Inc.
|
|
2
|
+
Copyright (c) 2015 Locus Energy
|
|
3
|
+
Copyright (c) 2013 James Casbon
|
|
4
|
+
Copyright (c) 2010 Bo Shi
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
7
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
8
|
+
the Software without restriction, including without limitation the rights to
|
|
9
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
10
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
|
11
|
+
so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sqlalchemy-vertica
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: Vertica dialect for SQLAlchemy 2.0+ with Async & Alembic support
|
|
5
|
+
Author-email: Luis Villamarin <luis@lv10.me>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/lv10/sqlalchemy-vertica
|
|
8
|
+
Project-URL: Documentation, https://github.com/lv10/sqlalchemy-vertica#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/lv10/sqlalchemy-vertica
|
|
10
|
+
Project-URL: Issues, https://github.com/lv10/sqlalchemy-vertica/issues
|
|
11
|
+
Project-URL: Funding, https://buymeacoffee.com/luisvillamg
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Topic :: Database
|
|
22
|
+
Classifier: Topic :: Database :: Front-Ends
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Description-Content-Type: text/x-rst
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: sqlalchemy>=2.0.0
|
|
27
|
+
Requires-Dist: typing_extensions>=4.6.0
|
|
28
|
+
Provides-Extra: vertica-python
|
|
29
|
+
Requires-Dist: vertica-python>=1.0.0; extra == "vertica-python"
|
|
30
|
+
Provides-Extra: asyncio
|
|
31
|
+
Requires-Dist: vertica-python>=1.0.0; extra == "asyncio"
|
|
32
|
+
Requires-Dist: greenlet>=3.0.0; extra == "asyncio"
|
|
33
|
+
Provides-Extra: pyodbc
|
|
34
|
+
Requires-Dist: pyodbc>=4.0.35; extra == "pyodbc"
|
|
35
|
+
Provides-Extra: turbodbc
|
|
36
|
+
Requires-Dist: turbodbc>=4.0.0; extra == "turbodbc"
|
|
37
|
+
Provides-Extra: alembic
|
|
38
|
+
Requires-Dist: alembic>=1.11.0; extra == "alembic"
|
|
39
|
+
Provides-Extra: all
|
|
40
|
+
Requires-Dist: vertica-python>=1.0.0; extra == "all"
|
|
41
|
+
Requires-Dist: greenlet>=3.0.0; extra == "all"
|
|
42
|
+
Requires-Dist: pyodbc>=4.0.35; extra == "all"
|
|
43
|
+
Requires-Dist: turbodbc>=4.0.0; extra == "all"
|
|
44
|
+
Requires-Dist: alembic>=1.11.0; extra == "all"
|
|
45
|
+
Dynamic: license-file
|
|
46
|
+
|
|
47
|
+
sqlalchemy-vertica
|
|
48
|
+
==================
|
|
49
|
+
|
|
50
|
+
Modern **Vertica Analytic Database** dialect for **SQLAlchemy 2.0+** with full support for **Async operations**, **Alembic migrations**, and modern Python (3.9 - 3.14+).
|
|
51
|
+
|
|
52
|
+
.. image:: https://img.shields.io/pypi/v/sqlalchemy-vertica.svg
|
|
53
|
+
:target: https://pypi.org/project/sqlalchemy-vertica/
|
|
54
|
+
.. image:: https://img.shields.io/badge/SQLAlchemy-2.0+-blue.svg
|
|
55
|
+
:target: https://www.sqlalchemy.org/
|
|
56
|
+
.. image:: https://img.shields.io/badge/python-3.9+-blue.svg
|
|
57
|
+
:target: https://www.python.org/
|
|
58
|
+
.. image:: https://img.shields.io/badge/Vertica-11--24+-green.svg
|
|
59
|
+
:target: https://www.vertica.com/
|
|
60
|
+
.. image:: https://img.shields.io/badge/license-MIT-green.svg
|
|
61
|
+
:target: https://opensource.org/licenses/MIT
|
|
62
|
+
.. image:: https://github.com/lv10/sqlalchemy-vertica/actions/workflows/ci.yml/badge.svg
|
|
63
|
+
:target: https://github.com/lv10/sqlalchemy-vertica/actions/workflows/ci.yml
|
|
64
|
+
.. image:: https://img.shields.io/badge/Buy%20Me%20a%20Coffee-Donate-yellow.svg
|
|
65
|
+
:target: https://buymeacoffee.com/luisvillamg
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
Features
|
|
69
|
+
--------
|
|
70
|
+
|
|
71
|
+
* **Full SQLAlchemy 2.0+ Architecture**: Built on ``DefaultDialect`` with query caching (``supports_statement_cache = True``), 2.0 execution semantics, and parameter-bound reflection.
|
|
72
|
+
* **First-Class Async Engine Support**: Run queries asynchronously with ``create_async_engine()`` and ``AsyncSession`` via ``vertica+vertica_python_async://`` without blocking the asyncio event loop.
|
|
73
|
+
* **Alembic Migrations**: Native ``VerticaImpl`` integration with transactional DDL, type synonym resolution, and index no-op handling (since Vertica utilizes projections).
|
|
74
|
+
* **Multi-Driver Support**:
|
|
75
|
+
* ``vertica-python`` (Synchronous pure-Python DBAPI driver)
|
|
76
|
+
* ``vertica-python-async`` (Asynchronous DBAPI adapter for non-blocking asyncio / FastAPI apps)
|
|
77
|
+
* ``pyodbc`` (ODBC driver)
|
|
78
|
+
* ``turbodbc`` (High-speed ODBC driver for Arrow / NumPy / Pandas data workflows)
|
|
79
|
+
* **Rich Vertica Data Types**:
|
|
80
|
+
* Geospatial: ``GEOMETRY``, ``GEOGRAPHY``
|
|
81
|
+
* Identifiers: native ``UUID``
|
|
82
|
+
* Large objects: ``LONG VARCHAR``, ``LONG VARBINARY`` (up to 32MB)
|
|
83
|
+
* Complex types: ``ARRAY``, ``MAP``, ``ROW`` (Vertica 10+)
|
|
84
|
+
* Temporal: ``TIMESTAMPTZ``, ``TIMETZ``, ``INTERVAL``
|
|
85
|
+
* **Complete Reflection**: Automatic introspection of schemas, tables, temp tables, views, view definitions, columns, primary keys, foreign keys, unique constraints, check constraints, table & column comments.
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
Installation
|
|
89
|
+
------------
|
|
90
|
+
|
|
91
|
+
Install from PyPI with your desired driver extras:
|
|
92
|
+
|
|
93
|
+
.. code-block:: bash
|
|
94
|
+
|
|
95
|
+
# Pure Python sync driver (recommended for sync applications)
|
|
96
|
+
pip install "sqlalchemy-vertica[vertica-python]"
|
|
97
|
+
|
|
98
|
+
# Pure Python async driver (for AsyncEngine / FastAPI / asyncio)
|
|
99
|
+
pip install "sqlalchemy-vertica[asyncio]"
|
|
100
|
+
|
|
101
|
+
# ODBC drivers
|
|
102
|
+
pip install "sqlalchemy-vertica[pyodbc]"
|
|
103
|
+
pip install "sqlalchemy-vertica[turbodbc]"
|
|
104
|
+
|
|
105
|
+
# Alembic migrations support
|
|
106
|
+
pip install "sqlalchemy-vertica[alembic]"
|
|
107
|
+
|
|
108
|
+
# Install all drivers and tools
|
|
109
|
+
pip install "sqlalchemy-vertica[all]"
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
Connection Strings
|
|
113
|
+
------------------
|
|
114
|
+
|
|
115
|
+
.. code-block:: python
|
|
116
|
+
|
|
117
|
+
import sqlalchemy as sa
|
|
118
|
+
from sqlalchemy.ext.asyncio import create_async_engine
|
|
119
|
+
|
|
120
|
+
# 1. Async (for FastAPI / asyncio applications)
|
|
121
|
+
async_engine = create_async_engine(
|
|
122
|
+
"vertica+vertica_python_async://user:pwd@host:5433/database?connection_timeout=10"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# 2. Sync vertica-python
|
|
126
|
+
engine = sa.create_engine(
|
|
127
|
+
"vertica+vertica_python://user:pwd@host:5433/database?connection_timeout=10"
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# 3. PyODBC with connection string
|
|
131
|
+
engine_pyodbc = sa.create_engine(
|
|
132
|
+
"vertica+pyodbc:///?odbc_connect=DSN%3DVerticaDSN"
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# 4. Turbodbc with DSN
|
|
136
|
+
engine_turbodbc = sa.create_engine(
|
|
137
|
+
"vertica+turbodbc:///?DSN=VerticaDSN"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
Quick Start
|
|
142
|
+
-----------
|
|
143
|
+
|
|
144
|
+
Synchronous SQLAlchemy 2.0
|
|
145
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
146
|
+
|
|
147
|
+
.. code-block:: python
|
|
148
|
+
|
|
149
|
+
from sqlalchemy import create_engine, text
|
|
150
|
+
|
|
151
|
+
engine = create_engine("vertica+vertica_python://user:pwd@localhost:5433/mydb")
|
|
152
|
+
|
|
153
|
+
with engine.connect() as conn:
|
|
154
|
+
result = conn.execute(text("SELECT version()"))
|
|
155
|
+
print(result.scalar())
|
|
156
|
+
|
|
157
|
+
# Transaction block
|
|
158
|
+
with engine.begin() as conn:
|
|
159
|
+
conn.execute(
|
|
160
|
+
text("INSERT INTO my_table (name) VALUES (:name)"),
|
|
161
|
+
{"name": "Alice"}
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
Asynchronous SQLAlchemy 2.0 & FastAPI
|
|
166
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
167
|
+
|
|
168
|
+
.. code-block:: python
|
|
169
|
+
|
|
170
|
+
import asyncio
|
|
171
|
+
from sqlalchemy import text
|
|
172
|
+
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
|
|
173
|
+
|
|
174
|
+
async def main():
|
|
175
|
+
engine = create_async_engine(
|
|
176
|
+
"vertica+vertica_python_async://user:pwd@localhost:5433/mydb",
|
|
177
|
+
pool_size=10,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
async with engine.connect() as conn:
|
|
181
|
+
result = await conn.execute(text("SELECT 1"))
|
|
182
|
+
print(result.scalar())
|
|
183
|
+
|
|
184
|
+
# Using AsyncSession
|
|
185
|
+
session_factory = async_sessionmaker(engine, class_=AsyncSession)
|
|
186
|
+
async with session_factory() as session:
|
|
187
|
+
result = await session.execute(text("SELECT COUNT(*) FROM my_table"))
|
|
188
|
+
print("Count:", result.scalar())
|
|
189
|
+
|
|
190
|
+
await engine.dispose()
|
|
191
|
+
|
|
192
|
+
asyncio.run(main())
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
Alembic Migrations
|
|
196
|
+
------------------
|
|
197
|
+
|
|
198
|
+
In your Alembic ``env.py``, simply import ``sqlalchemy_vertica``:
|
|
199
|
+
|
|
200
|
+
.. code-block:: python
|
|
201
|
+
|
|
202
|
+
import sqlalchemy_vertica # Registers VerticaImpl plugin automatically
|
|
203
|
+
from alembic import context
|
|
204
|
+
|
|
205
|
+
# configure context
|
|
206
|
+
context.configure(
|
|
207
|
+
connection=connection,
|
|
208
|
+
target_metadata=target_metadata,
|
|
209
|
+
transactional_ddl=True,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
Vertica does not support traditional B-tree indexes (it utilizes projections). ``sqlalchemy-vertica`` treats index creation/dropping as safe no-ops in migrations to ensure multi-database migration scripts run seamlessly.
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
Custom Data Types
|
|
216
|
+
-----------------
|
|
217
|
+
|
|
218
|
+
.. code-block:: python
|
|
219
|
+
|
|
220
|
+
from sqlalchemy import Column, Integer, Table, MetaData
|
|
221
|
+
from sqlalchemy_vertica import (
|
|
222
|
+
GEOMETRY,
|
|
223
|
+
GEOGRAPHY,
|
|
224
|
+
UUID,
|
|
225
|
+
LONG_VARCHAR,
|
|
226
|
+
ARRAY,
|
|
227
|
+
MAP,
|
|
228
|
+
ROW,
|
|
229
|
+
TIMESTAMPTZ,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
metadata = MetaData()
|
|
233
|
+
|
|
234
|
+
places = Table(
|
|
235
|
+
"places",
|
|
236
|
+
metadata,
|
|
237
|
+
Column("id", Integer, primary_key=True, autoincrement=True),
|
|
238
|
+
Column("guid", UUID, nullable=False),
|
|
239
|
+
Column("description", LONG_VARCHAR),
|
|
240
|
+
Column("location", GEOMETRY(srid=4326)),
|
|
241
|
+
Column("tags", ARRAY(LONG_VARCHAR)),
|
|
242
|
+
Column("metadata", MAP(LONG_VARCHAR, LONG_VARCHAR)),
|
|
243
|
+
Column("created_at", TIMESTAMPTZ),
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
Testing & Coverage
|
|
248
|
+
------------------
|
|
249
|
+
|
|
250
|
+
Run the automated test suite with ``pytest`` and ``pytest-cov``:
|
|
251
|
+
|
|
252
|
+
.. code-block:: bash
|
|
253
|
+
|
|
254
|
+
pytest -v --cov=sqlalchemy_vertica --cov-report=term-missing
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
Support
|
|
258
|
+
-------
|
|
259
|
+
|
|
260
|
+
If you find this project helpful and want to support its maintenance and development, you can buy me a coffee:
|
|
261
|
+
|
|
262
|
+
.. image:: https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png
|
|
263
|
+
:target: https://www.buymeacoffee.com/luisvillamg
|
|
264
|
+
:alt: Buy Me A Coffee
|
|
265
|
+
:width: 180px
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
License
|
|
269
|
+
-------
|
|
270
|
+
|
|
271
|
+
MIT License. See `LICENSE` for details.
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
sqlalchemy-vertica
|
|
2
|
+
==================
|
|
3
|
+
|
|
4
|
+
Modern **Vertica Analytic Database** dialect for **SQLAlchemy 2.0+** with full support for **Async operations**, **Alembic migrations**, and modern Python (3.9 - 3.14+).
|
|
5
|
+
|
|
6
|
+
.. image:: https://img.shields.io/pypi/v/sqlalchemy-vertica.svg
|
|
7
|
+
:target: https://pypi.org/project/sqlalchemy-vertica/
|
|
8
|
+
.. image:: https://img.shields.io/badge/SQLAlchemy-2.0+-blue.svg
|
|
9
|
+
:target: https://www.sqlalchemy.org/
|
|
10
|
+
.. image:: https://img.shields.io/badge/python-3.9+-blue.svg
|
|
11
|
+
:target: https://www.python.org/
|
|
12
|
+
.. image:: https://img.shields.io/badge/Vertica-11--24+-green.svg
|
|
13
|
+
:target: https://www.vertica.com/
|
|
14
|
+
.. image:: https://img.shields.io/badge/license-MIT-green.svg
|
|
15
|
+
:target: https://opensource.org/licenses/MIT
|
|
16
|
+
.. image:: https://github.com/lv10/sqlalchemy-vertica/actions/workflows/ci.yml/badge.svg
|
|
17
|
+
:target: https://github.com/lv10/sqlalchemy-vertica/actions/workflows/ci.yml
|
|
18
|
+
.. image:: https://img.shields.io/badge/Buy%20Me%20a%20Coffee-Donate-yellow.svg
|
|
19
|
+
:target: https://buymeacoffee.com/luisvillamg
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
Features
|
|
23
|
+
--------
|
|
24
|
+
|
|
25
|
+
* **Full SQLAlchemy 2.0+ Architecture**: Built on ``DefaultDialect`` with query caching (``supports_statement_cache = True``), 2.0 execution semantics, and parameter-bound reflection.
|
|
26
|
+
* **First-Class Async Engine Support**: Run queries asynchronously with ``create_async_engine()`` and ``AsyncSession`` via ``vertica+vertica_python_async://`` without blocking the asyncio event loop.
|
|
27
|
+
* **Alembic Migrations**: Native ``VerticaImpl`` integration with transactional DDL, type synonym resolution, and index no-op handling (since Vertica utilizes projections).
|
|
28
|
+
* **Multi-Driver Support**:
|
|
29
|
+
* ``vertica-python`` (Synchronous pure-Python DBAPI driver)
|
|
30
|
+
* ``vertica-python-async`` (Asynchronous DBAPI adapter for non-blocking asyncio / FastAPI apps)
|
|
31
|
+
* ``pyodbc`` (ODBC driver)
|
|
32
|
+
* ``turbodbc`` (High-speed ODBC driver for Arrow / NumPy / Pandas data workflows)
|
|
33
|
+
* **Rich Vertica Data Types**:
|
|
34
|
+
* Geospatial: ``GEOMETRY``, ``GEOGRAPHY``
|
|
35
|
+
* Identifiers: native ``UUID``
|
|
36
|
+
* Large objects: ``LONG VARCHAR``, ``LONG VARBINARY`` (up to 32MB)
|
|
37
|
+
* Complex types: ``ARRAY``, ``MAP``, ``ROW`` (Vertica 10+)
|
|
38
|
+
* Temporal: ``TIMESTAMPTZ``, ``TIMETZ``, ``INTERVAL``
|
|
39
|
+
* **Complete Reflection**: Automatic introspection of schemas, tables, temp tables, views, view definitions, columns, primary keys, foreign keys, unique constraints, check constraints, table & column comments.
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
Installation
|
|
43
|
+
------------
|
|
44
|
+
|
|
45
|
+
Install from PyPI with your desired driver extras:
|
|
46
|
+
|
|
47
|
+
.. code-block:: bash
|
|
48
|
+
|
|
49
|
+
# Pure Python sync driver (recommended for sync applications)
|
|
50
|
+
pip install "sqlalchemy-vertica[vertica-python]"
|
|
51
|
+
|
|
52
|
+
# Pure Python async driver (for AsyncEngine / FastAPI / asyncio)
|
|
53
|
+
pip install "sqlalchemy-vertica[asyncio]"
|
|
54
|
+
|
|
55
|
+
# ODBC drivers
|
|
56
|
+
pip install "sqlalchemy-vertica[pyodbc]"
|
|
57
|
+
pip install "sqlalchemy-vertica[turbodbc]"
|
|
58
|
+
|
|
59
|
+
# Alembic migrations support
|
|
60
|
+
pip install "sqlalchemy-vertica[alembic]"
|
|
61
|
+
|
|
62
|
+
# Install all drivers and tools
|
|
63
|
+
pip install "sqlalchemy-vertica[all]"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
Connection Strings
|
|
67
|
+
------------------
|
|
68
|
+
|
|
69
|
+
.. code-block:: python
|
|
70
|
+
|
|
71
|
+
import sqlalchemy as sa
|
|
72
|
+
from sqlalchemy.ext.asyncio import create_async_engine
|
|
73
|
+
|
|
74
|
+
# 1. Async (for FastAPI / asyncio applications)
|
|
75
|
+
async_engine = create_async_engine(
|
|
76
|
+
"vertica+vertica_python_async://user:pwd@host:5433/database?connection_timeout=10"
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# 2. Sync vertica-python
|
|
80
|
+
engine = sa.create_engine(
|
|
81
|
+
"vertica+vertica_python://user:pwd@host:5433/database?connection_timeout=10"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# 3. PyODBC with connection string
|
|
85
|
+
engine_pyodbc = sa.create_engine(
|
|
86
|
+
"vertica+pyodbc:///?odbc_connect=DSN%3DVerticaDSN"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# 4. Turbodbc with DSN
|
|
90
|
+
engine_turbodbc = sa.create_engine(
|
|
91
|
+
"vertica+turbodbc:///?DSN=VerticaDSN"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
Quick Start
|
|
96
|
+
-----------
|
|
97
|
+
|
|
98
|
+
Synchronous SQLAlchemy 2.0
|
|
99
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
100
|
+
|
|
101
|
+
.. code-block:: python
|
|
102
|
+
|
|
103
|
+
from sqlalchemy import create_engine, text
|
|
104
|
+
|
|
105
|
+
engine = create_engine("vertica+vertica_python://user:pwd@localhost:5433/mydb")
|
|
106
|
+
|
|
107
|
+
with engine.connect() as conn:
|
|
108
|
+
result = conn.execute(text("SELECT version()"))
|
|
109
|
+
print(result.scalar())
|
|
110
|
+
|
|
111
|
+
# Transaction block
|
|
112
|
+
with engine.begin() as conn:
|
|
113
|
+
conn.execute(
|
|
114
|
+
text("INSERT INTO my_table (name) VALUES (:name)"),
|
|
115
|
+
{"name": "Alice"}
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
Asynchronous SQLAlchemy 2.0 & FastAPI
|
|
120
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
121
|
+
|
|
122
|
+
.. code-block:: python
|
|
123
|
+
|
|
124
|
+
import asyncio
|
|
125
|
+
from sqlalchemy import text
|
|
126
|
+
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
|
|
127
|
+
|
|
128
|
+
async def main():
|
|
129
|
+
engine = create_async_engine(
|
|
130
|
+
"vertica+vertica_python_async://user:pwd@localhost:5433/mydb",
|
|
131
|
+
pool_size=10,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
async with engine.connect() as conn:
|
|
135
|
+
result = await conn.execute(text("SELECT 1"))
|
|
136
|
+
print(result.scalar())
|
|
137
|
+
|
|
138
|
+
# Using AsyncSession
|
|
139
|
+
session_factory = async_sessionmaker(engine, class_=AsyncSession)
|
|
140
|
+
async with session_factory() as session:
|
|
141
|
+
result = await session.execute(text("SELECT COUNT(*) FROM my_table"))
|
|
142
|
+
print("Count:", result.scalar())
|
|
143
|
+
|
|
144
|
+
await engine.dispose()
|
|
145
|
+
|
|
146
|
+
asyncio.run(main())
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
Alembic Migrations
|
|
150
|
+
------------------
|
|
151
|
+
|
|
152
|
+
In your Alembic ``env.py``, simply import ``sqlalchemy_vertica``:
|
|
153
|
+
|
|
154
|
+
.. code-block:: python
|
|
155
|
+
|
|
156
|
+
import sqlalchemy_vertica # Registers VerticaImpl plugin automatically
|
|
157
|
+
from alembic import context
|
|
158
|
+
|
|
159
|
+
# configure context
|
|
160
|
+
context.configure(
|
|
161
|
+
connection=connection,
|
|
162
|
+
target_metadata=target_metadata,
|
|
163
|
+
transactional_ddl=True,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
Vertica does not support traditional B-tree indexes (it utilizes projections). ``sqlalchemy-vertica`` treats index creation/dropping as safe no-ops in migrations to ensure multi-database migration scripts run seamlessly.
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
Custom Data Types
|
|
170
|
+
-----------------
|
|
171
|
+
|
|
172
|
+
.. code-block:: python
|
|
173
|
+
|
|
174
|
+
from sqlalchemy import Column, Integer, Table, MetaData
|
|
175
|
+
from sqlalchemy_vertica import (
|
|
176
|
+
GEOMETRY,
|
|
177
|
+
GEOGRAPHY,
|
|
178
|
+
UUID,
|
|
179
|
+
LONG_VARCHAR,
|
|
180
|
+
ARRAY,
|
|
181
|
+
MAP,
|
|
182
|
+
ROW,
|
|
183
|
+
TIMESTAMPTZ,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
metadata = MetaData()
|
|
187
|
+
|
|
188
|
+
places = Table(
|
|
189
|
+
"places",
|
|
190
|
+
metadata,
|
|
191
|
+
Column("id", Integer, primary_key=True, autoincrement=True),
|
|
192
|
+
Column("guid", UUID, nullable=False),
|
|
193
|
+
Column("description", LONG_VARCHAR),
|
|
194
|
+
Column("location", GEOMETRY(srid=4326)),
|
|
195
|
+
Column("tags", ARRAY(LONG_VARCHAR)),
|
|
196
|
+
Column("metadata", MAP(LONG_VARCHAR, LONG_VARCHAR)),
|
|
197
|
+
Column("created_at", TIMESTAMPTZ),
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
Testing & Coverage
|
|
202
|
+
------------------
|
|
203
|
+
|
|
204
|
+
Run the automated test suite with ``pytest`` and ``pytest-cov``:
|
|
205
|
+
|
|
206
|
+
.. code-block:: bash
|
|
207
|
+
|
|
208
|
+
pytest -v --cov=sqlalchemy_vertica --cov-report=term-missing
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
Support
|
|
212
|
+
-------
|
|
213
|
+
|
|
214
|
+
If you find this project helpful and want to support its maintenance and development, you can buy me a coffee:
|
|
215
|
+
|
|
216
|
+
.. image:: https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png
|
|
217
|
+
:target: https://www.buymeacoffee.com/luisvillamg
|
|
218
|
+
:alt: Buy Me A Coffee
|
|
219
|
+
:width: 180px
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
License
|
|
223
|
+
-------
|
|
224
|
+
|
|
225
|
+
MIT License. See `LICENSE` for details.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sqlalchemy-vertica"
|
|
7
|
+
version = "1.0.2"
|
|
8
|
+
description = "Vertica dialect for SQLAlchemy 2.0+ with Async & Alembic support"
|
|
9
|
+
readme = "README.rst"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
authors = [
|
|
12
|
+
{name = "Luis Villamarin", email = "luis@lv10.me"}
|
|
13
|
+
]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 5 - Production/Stable",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.9",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Programming Language :: Python :: 3.14",
|
|
24
|
+
"Topic :: Database",
|
|
25
|
+
"Topic :: Database :: Front-Ends",
|
|
26
|
+
]
|
|
27
|
+
requires-python = ">=3.9"
|
|
28
|
+
dependencies = [
|
|
29
|
+
"sqlalchemy>=2.0.0",
|
|
30
|
+
"typing_extensions>=4.6.0",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.optional-dependencies]
|
|
34
|
+
vertica-python = [
|
|
35
|
+
"vertica-python>=1.0.0",
|
|
36
|
+
]
|
|
37
|
+
asyncio = [
|
|
38
|
+
"vertica-python>=1.0.0",
|
|
39
|
+
"greenlet>=3.0.0",
|
|
40
|
+
]
|
|
41
|
+
pyodbc = [
|
|
42
|
+
"pyodbc>=4.0.35",
|
|
43
|
+
]
|
|
44
|
+
turbodbc = [
|
|
45
|
+
"turbodbc>=4.0.0",
|
|
46
|
+
]
|
|
47
|
+
alembic = [
|
|
48
|
+
"alembic>=1.11.0",
|
|
49
|
+
]
|
|
50
|
+
all = [
|
|
51
|
+
"vertica-python>=1.0.0",
|
|
52
|
+
"greenlet>=3.0.0",
|
|
53
|
+
"pyodbc>=4.0.35",
|
|
54
|
+
"turbodbc>=4.0.0",
|
|
55
|
+
"alembic>=1.11.0",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[project.urls]
|
|
59
|
+
Homepage = "https://github.com/lv10/sqlalchemy-vertica"
|
|
60
|
+
Documentation = "https://github.com/lv10/sqlalchemy-vertica#readme"
|
|
61
|
+
Repository = "https://github.com/lv10/sqlalchemy-vertica"
|
|
62
|
+
Issues = "https://github.com/lv10/sqlalchemy-vertica/issues"
|
|
63
|
+
Funding = "https://buymeacoffee.com/luisvillamg"
|
|
64
|
+
|
|
65
|
+
[dependency-groups]
|
|
66
|
+
dev = [
|
|
67
|
+
"pytest>=7.4.0",
|
|
68
|
+
"pytest-asyncio>=0.21.0",
|
|
69
|
+
"pytest-cov>=4.1.0",
|
|
70
|
+
"coverage[toml]>=7.3.0",
|
|
71
|
+
"ruff>=0.9.0",
|
|
72
|
+
"mypy>=1.5.0",
|
|
73
|
+
"python-semantic-release>=9.15.2",
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
[project.entry-points."sqlalchemy.dialects"]
|
|
77
|
+
vertica = "sqlalchemy_vertica.dialect_vertica_python:VerticaDialect"
|
|
78
|
+
"vertica.vertica_python" = "sqlalchemy_vertica.dialect_vertica_python:VerticaDialect"
|
|
79
|
+
"vertica.vertica_python_async" = "sqlalchemy_vertica.dialect_vertica_python_async:VerticaDialect_vertica_python_async"
|
|
80
|
+
"vertica.async_vertica_python" = "sqlalchemy_vertica.dialect_vertica_python_async:VerticaDialect_vertica_python_async"
|
|
81
|
+
"vertica.pyodbc" = "sqlalchemy_vertica.dialect_pyodbc:VerticaDialect"
|
|
82
|
+
"vertica.turbodbc" = "sqlalchemy_vertica.dialect_turbodbc:VerticaDialect"
|
|
83
|
+
|
|
84
|
+
[tool.setuptools.packages.find]
|
|
85
|
+
where = ["."]
|
|
86
|
+
include = ["sqlalchemy_vertica*"]
|
|
87
|
+
|
|
88
|
+
[tool.pytest.ini_options]
|
|
89
|
+
minversion = "7.0"
|
|
90
|
+
addopts = "-ra --cov=sqlalchemy_vertica --cov-report=term-missing"
|
|
91
|
+
testpaths = ["tests"]
|
|
92
|
+
asyncio_mode = "auto"
|
|
93
|
+
|
|
94
|
+
[tool.coverage.run]
|
|
95
|
+
source = ["sqlalchemy_vertica"]
|
|
96
|
+
branch = true
|
|
97
|
+
|
|
98
|
+
[tool.coverage.report]
|
|
99
|
+
show_missing = true
|
|
100
|
+
skip_covered = false
|
|
101
|
+
exclude_lines = [
|
|
102
|
+
"pragma: no cover",
|
|
103
|
+
"def __repr__",
|
|
104
|
+
"if TYPE_CHECKING:",
|
|
105
|
+
"raise NotImplementedError",
|
|
106
|
+
"\\.\\.\\.",
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
[tool.ruff]
|
|
110
|
+
target-version = "py39"
|
|
111
|
+
line-length = 100
|
|
112
|
+
exclude = [
|
|
113
|
+
".venv",
|
|
114
|
+
".git",
|
|
115
|
+
"__pycache__",
|
|
116
|
+
"dist",
|
|
117
|
+
"build",
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
[tool.ruff.lint]
|
|
121
|
+
select = [
|
|
122
|
+
"E",
|
|
123
|
+
"W",
|
|
124
|
+
"F",
|
|
125
|
+
"I",
|
|
126
|
+
"B",
|
|
127
|
+
"C4",
|
|
128
|
+
"UP",
|
|
129
|
+
]
|
|
130
|
+
ignore = [
|
|
131
|
+
"E501",
|
|
132
|
+
]
|
|
133
|
+
|
|
134
|
+
[tool.mypy]
|
|
135
|
+
python_version = "3.10"
|
|
136
|
+
warn_unused_configs = true
|
|
137
|
+
ignore_missing_imports = true
|
|
138
|
+
|
|
139
|
+
[tool.semantic_release]
|
|
140
|
+
version_toml = ["pyproject.toml:project.version"]
|
|
141
|
+
version_variables = ["sqlalchemy_vertica/__init__.py:__version__"]
|
|
142
|
+
tag_format = "{version}"
|
|
143
|
+
build_command = "uv build"
|
|
144
|
+
|
|
145
|
+
[tool.semantic_release.branches.main]
|
|
146
|
+
match = "(main|master)"
|
|
147
|
+
prerelease = false
|
|
148
|
+
|
|
149
|
+
[tool.semantic_release.changelog]
|
|
150
|
+
exclude_commit_patterns = []
|
|
151
|
+
|
|
152
|
+
[tool.semantic_release.changelog.environment]
|
|
153
|
+
block_start_string = "{%"
|
|
154
|
+
block_end_string = "%}"
|
|
155
|
+
variable_start_string = "{{"
|
|
156
|
+
variable_end_string = "}}"
|
|
157
|
+
comment_start_string = "{#"
|
|
158
|
+
comment_end_string = "#}"
|
|
159
|
+
trim_blocks = false
|
|
160
|
+
lstrip_blocks = false
|
|
161
|
+
newline_sequence = "\n"
|
|
162
|
+
keep_trailing_newline = false
|
|
163
|
+
extensions = []
|
|
164
|
+
autoescape = true
|
|
165
|
+
|
|
166
|
+
[tool.semantic_release.commit_author]
|
|
167
|
+
env = "GIT_COMMIT_AUTHOR"
|
|
168
|
+
default = "semantic-release <semantic-release>"
|
|
169
|
+
|
|
170
|
+
[tool.semantic_release.commit_parser_options]
|
|
171
|
+
allowed_tags = ["build", "chore", "ci", "docs", "feat", "fix", "perf", "style", "refactor", "test"]
|
|
172
|
+
minor_tags = ["feat"]
|
|
173
|
+
patch_tags = ["fix", "perf"]
|
|
174
|
+
default_bump_level = 0
|
|
175
|
+
|
|
176
|
+
[tool.semantic_release.remote]
|
|
177
|
+
name = "origin"
|
|
178
|
+
type = "github"
|
|
179
|
+
token = { env = "GH_TOKEN" }
|
|
180
|
+
|
|
181
|
+
[tool.semantic_release.publish]
|
|
182
|
+
dist_glob_patterns = ["dist/*"]
|
|
183
|
+
upload_to_vcs_release = true
|