Skip to content

Commit a7ec9d0

Browse files
committed
统一项目名为 gaussdb-sqlalchemy-python-driver
- pyproject.toml: name 改为 gaussdb-sqlalchemy-python-driver - GitHub URL 更新为 GaussDB-SQLAlchemy-Python-Driver - 内置 JDBC 驱动 jar 到 whl 包,无需单独下载 - jdbc_driver_path 未指定时自动使用包内 jar - README 重写:更新兼容模式说明(A=Oracle, B/M=MySQL) - requires-python 改为 >=3.8 - 修复 BUG 16/18/21/22 (M兼容 TIMESTAMP/concat/lastrowid/LargeBinary) - 修复测试脚本问题 (edge_cases5-12 全部通过) - 打包产物加入 dist/
1 parent a34d5d7 commit a7ec9d0

18 files changed

Lines changed: 5366 additions & 129 deletions

.gitignore

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@ __pycache__/
77
.venv/
88
.idea/
99
build/
10-
dist/
1110
release/
1211
*.egg-info/
1312
_local/
14-
tests/test_edge_cases.py
15-
tests/test_edge_cases2.py
16-
tests/test_edge_cases3.py

README.md

Lines changed: 109 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,187 +1,179 @@
11
# GaussDB SQLAlchemy Python 驱动
22

3-
这是一个面向华为 GaussDB 轻量化集中式 505.1 的 Python SQLAlchemy 方言项目,当前客户目标兼容模式为 A 兼容、B 兼容和 M 兼容。
3+
面向华为 GaussDB 轻量化集中式的 Python SQLAlchemy 方言驱动。通过 JayDeBeApi/JPype 调用 GaussDB JDBC Driver,接入 SQLAlchemy 的 ORM、连接池、事务、SQL 编译和反射能力。支持 A 兼容(Oracle 风格)、B 兼容(MySQL 风格)和 M 兼容(MySQL 风格)三种模式
44

5-
项目采用 JDBC 后端:Python 通过 JayDeBeApi/JPype 调用 GaussDB JDBC Driver,再接入 SQLAlchemy 的 ORM、连接池、事务、SQL 编译和反射能力。该方案面向 Windows 免数据库客户端 DLL 的交付场景
5+
JDBC 驱动 jar 已内置在 whl 包中,Windows 上不需要额外安装数据库客户端 DLL,也不需要单独下载 JDBC 驱动
66

7-
## 功能特性
7+
## 前置条件
88

9-
- 支持 SQLAlchemy 2.x
10-
- 支持 `gaussdb://...` 连接串
11-
- 支持 `gaussdb+jdbc://...` 连接串
12-
- 底层使用 JayDeBeApi、JPype1 和 GaussDB JDBC Driver
13-
- Windows 不需要额外安装数据库客户端 DLL
14-
- 面向 GaussDB 轻量化集中式 505.1 的 A 兼容、B 兼容和 M 兼容场景
15-
- 默认关闭 HSTORE 等 PostgreSQL 扩展假设,适合轻量化集中式部署
9+
- Python 3.8 及以上
10+
- JRE 或 JDK 8 及以上(Java 运行环境)
1611

1712
## 安装
1813

19-
### Windows
20-
21-
```powershell
22-
py -3.11 -m venv .venv
23-
.\.venv\Scripts\Activate.ps1
24-
python -m pip install --upgrade pip
25-
python -m pip install gaussdb_sqlalchemy_driver-0.1.0-py3-none-any.whl
26-
```
27-
28-
还需要准备:
29-
30-
- Java Runtime,建议 JDK/JRE 8 或 11 及以上
31-
- GaussDB JDBC Driver jar,例如 `gsjdbc4.jar`
32-
33-
### Linux 或 macOS
34-
3514
```bash
36-
python3 -m venv .venv
37-
. .venv/bin/activate
38-
python -m pip install --upgrade pip
39-
python -m pip install gaussdb_sqlalchemy_driver-0.1.0-py3-none-any.whl
15+
pip install gaussdb_sqlalchemy_driver-0.1.0-py3-none-any.whl
4016
```
4117

42-
## SQLAlchemy 使用示例
18+
安装后自动拉取 SQLAlchemy、JayDeBeApi、JPype1 三个依赖。JDBC 驱动 jar 已内置,无需额外下载。
19+
20+
## 快速开始
4321

4422
```python
4523
from sqlalchemy import create_engine, text
4624

25+
# 不需要指定 jar 路径,driver 自动使用包内置的 JDBC 驱动
4726
engine = create_engine(
48-
"gaussdb+jdbc://user:password@127.0.0.1:8000/postgres"
49-
"?jdbc_driver_path=C:/GaussDB/jdbc/gsjdbc4.jar",
27+
"gaussdb+jdbc://sqlbuilder1:huawei%40123@127.0.0.1:8000/postgres?sslmode=disable",
5028
pool_pre_ping=True,
5129
)
5230

53-
with engine.begin() as conn:
31+
with engine.connect() as conn:
5432
print(conn.execute(text("select 1")).scalar_one())
5533
```
5634

57-
默认 JDBC 驱动类名为:
58-
59-
```text
60-
com.huawei.gaussdb.jdbc.Driver
61-
```
35+
密码中如包含 `@` 等特殊字符,需要 URL 编码。例如 `password@123` 应写为 `password%40123`
6236

63-
当前华为 GaussDB JDBC jar 使用该驱动类名。如果实际 jar 使用其他驱动类名,可以显式指定:
37+
## 连接串格式
6438

6539
```text
66-
gaussdb+jdbc://user:password@127.0.0.1:8000/postgres?jdbc_driver_class=com.huawei.gaussdb.jdbc.Driver&jdbc_driver_path=C:/GaussDB/jdbc/gaussdbjdbc-506.0.0.b058-jdk7.jar
40+
gaussdb+jdbc://用户名:密码@主机:端口/数据库名?sslmode=disable
6741
```
6842

69-
也可以完全覆盖 JDBC URL
43+
也支持短格式
7044

7145
```text
72-
gaussdb+jdbc://user:password@placeholder/postgres?jdbc_url=jdbc:gaussdb://127.0.0.1:8000/postgres&jdbc_driver_path=C:/GaussDB/jdbc/gaussdbjdbc-506.0.0.b058-jdk7.jar
46+
gaussdb://用户名:密码@主机:端口/数据库名?sslmode=disable
7347
```
7448

75-
## 连接串格式
76-
77-
推荐格式:
49+
如果需要使用自己的 JDBC 驱动(比如不同版本),可以通过 `jdbc_driver_path` 覆盖内置驱动:
7850

7951
```text
80-
gaussdb+jdbc://用户名:密码@主机:端口/数据库名?jdbc_driver_path=JDBC驱动jar路径
52+
gaussdb+jdbc://用户名:密码@主机:端口/数据库名?jdbc_driver_path=/path/to/your/gsjdbc4.jar&sslmode=disable
8153
```
8254

83-
短格式 `gaussdb://...` 也会使用 JDBC 方言
55+
其他可选参数
8456

85-
```text
86-
gaussdb://用户名:密码@主机:端口/数据库名?jdbc_driver_path=JDBC驱动jar路径
87-
```
57+
- `jdbc_driver_class` — 指定 JDBC 驱动类名,默认 `com.huawei.gaussdb.jdbc.Driver`
58+
- `jdbc_url` — 完全覆盖底层 JDBC URL
8859

89-
密码中如包含 `@` 等特殊字符,需要 URL 编码。例如 `password@123` 应写为 `password%40123`
60+
## ORM 用法
9061

91-
## 开发和测试
62+
```python
63+
from sqlalchemy import create_engine, Column, Integer, String, DateTime
64+
from sqlalchemy.orm import Session, declarative_base
65+
from datetime import datetime
9266

93-
```bash
94-
python3 -m venv .venv
95-
. .venv/bin/activate
96-
python -m pip install --upgrade pip
97-
python -m pip install -e ".[test]"
98-
pytest
99-
```
67+
engine = create_engine(
68+
"gaussdb+jdbc://sqlbuilder1:huawei%40123@127.0.0.1:8000/testm?sslmode=disable",
69+
pool_pre_ping=True,
70+
)
10071

101-
如果要连接真实 GaussDB 环境执行集成测试,可以设置:
72+
Base = declarative_base()
10273

103-
```bash
104-
export GAUSSDB_TEST_URL='gaussdb+jdbc://user:password@host:port/postgres?jdbc_driver_path=/path/to/gsjdbc4.jar'
105-
pytest -m integration
106-
```
74+
class User(Base):
75+
__tablename__ = "users"
76+
id = Column(Integer, primary_key=True)
77+
name = Column(String(50))
78+
created = Column(DateTime)
10779

108-
如果要一次性验证 A/B/M 三种兼容库,可以分别设置:
80+
Base.metadata.create_all(engine)
10981

110-
```bash
111-
export GAUSSDB_TEST_URL_A='gaussdb+jdbc://user:password@host:port/a_database?jdbc_driver_path=/path/to/gaussdbjdbc.jar'
112-
export GAUSSDB_TEST_URL_B='gaussdb+jdbc://user:password@host:port/b_database?jdbc_driver_path=/path/to/gaussdbjdbc.jar'
113-
export GAUSSDB_TEST_URL_M='gaussdb+jdbc://user:password@host:port/m_database?jdbc_driver_path=/path/to/gaussdbjdbc.jar'
114-
pytest tests/test_compatibility_scenarios.py -m integration
82+
with Session(engine) as session:
83+
session.add(User(name="张三", created=datetime.now()))
84+
session.commit()
85+
users = session.query(User).all()
86+
for u in users:
87+
print(u.id, u.name, u.created)
11588
```
11689

117-
也可以使用逗号分隔的 `GAUSSDB_TEST_URLS` 批量传入多个真实库连接串。
118-
119-
没有安装 pytest 的数据库主机也可以运行轻量探针:
120-
121-
```bash
122-
GAUSSDB_TEST_URL='gaussdb+jdbc://user:password@host:port/postgres?jdbc_driver_path=/path/to/gsjdbc4.jar' \
123-
python scripts/run_integration_probe.py
124-
```
90+
## 兼容模式支持
12591

126-
如果要快速判断当前库对 PostgreSQL、Oracle 风格、MySQL 风格 SQL 的接受情况,可以运行
92+
驱动自动检测数据库的兼容模式(A/B/M)并适配 SQL 方言差异
12793

128-
```bash
129-
GAUSSDB_TEST_URL='gaussdb+jdbc://user:password@host:port/postgres?jdbc_driver_path=/path/to/gsjdbc4.jar' \
130-
python scripts/run_syntax_probe.py
131-
```
94+
| 特性 | A 兼容 (Oracle) | B 兼容 (MySQL) | M 兼容 (MySQL) |
95+
|------|----------------|----------------|----------------|
96+
| 标识符引号 | 双引号 | 双引号/反引号 | 反引号 |
97+
| 自增主键 | serial | serial/AUTO_INCREMENT | AUTO_INCREMENT |
98+
| ORM INSERT 获取自增 ID | RETURNING | RETURNING | LAST_INSERT_ID() |
99+
| 字符串拼接 | \|\| | \|\| | CONCAT() |
100+
| TIMESTAMP 精度 | 默认无 | 默认无 | TIMESTAMP(6) |
101+
| Oracle 语法 (DUAL/NVL/SYSDATE) | 支持 | 支持 | 不支持 |
102+
| 隔离级别 | 全部支持 | 全部支持 | REPEATABLE READ(SERIALIZABLE 不支持) |
132103

133-
Windows 实机测试步骤、前置条件、测试场景和真实数据库地址配置方式见 [docs/Windows测试指导手册.md](docs/Windows测试指导手册.md)
104+
驱动还支持 Alembic 迁移工具,包括 batch_alter_table 和 autogenerate
134105

135-
## 验证覆盖
106+
## 功能特性
136107

137-
集成测试覆盖:
108+
- SQLAlchemy 2.x Core + ORM 完整支持
109+
- 连接池、事务、保存点
110+
- 表/列/索引/约束/视图/注释反射
111+
- Alembic 迁移集成(batch mode + autogenerate)
112+
- 全部标准 SQL 数据类型(Integer、String、Text、DateTime、Numeric、Boolean、LargeBinary 等)
113+
- A/B/M 三种兼容模式自动检测和适配
138114

139-
- SQLAlchemy Core DDL、DML、查询
140-
- 真实表生命周期:建表、表存在性检查、插入、查询、更新、删除和清理
141-
- 事务回滚
142-
- 批量插入
143-
- ORM CRUD
144-
- 元数据反射
145-
- 常用数据类型
146-
- 主键、唯一约束、普通索引反射
147-
- 序列和默认值
148-
- Alembic Operations
149-
- Alembic autogenerate 基础无差异检测
150-
- 复杂索引、表达式索引、视图反射和分区表反射
151-
- 连接池基础复用
152-
- A/B/M 兼容语法场景,包括 Oracle 风格、MySQL 风格、`serial``auto_increment``nextval` 和表达式索引
115+
## 已知限制
153116

154-
## 适配范围
117+
- **ON CONFLICT**:GaussDB 集中式不支持 PostgreSQL `ON CONFLICT` upsert 语法
118+
- **M 兼容 LIKE**:默认大小写不敏感(MySQL 行为);A/B 兼容为大小写敏感
119+
- **M 兼容集合运算**:不支持 `INTERSECT` / `EXCEPT`
120+
- **M 兼容临时表**:不支持 `CREATE TEMP TABLE`,需用 `CREATE TEMPORARY TABLE`
121+
- **M 兼容 CAST**:不支持 `CAST(x AS VARCHAR)`,需用 `CAST(x AS CHAR)`
122+
- **M 兼容 TIMESTAMP DEFAULT**`TIMESTAMP(6) DEFAULT current_timestamp` 不被支持
123+
- **M 兼容 TEXT**:最大 65535 字节
124+
- **Decimal 精度**:GaussDB/JDBC 侧对超过 15 位有效数字的 Decimal 有精度损失
125+
- **SERIALIZABLE 隔离级别**:GaussDB 集中式不支持,静默降级为 REPEATABLE READ
155126

156-
当前版本面向 GaussDB 轻量化集中式 505.1 的 A 兼容、B 兼容和 M 兼容基础 SQLAlchemy 接入场景,适合应用侧先完成连接、查询、事务、连接池和 ORM 基础能力适配。
127+
## 并发限制
157128

158-
已在 GaussDB Kernel 507.0.0 环境验证过 A 兼容、B 兼容和 M 兼容基础能力。GaussDB 505.1、Windows 实机和客户真实库仍需按测试指导手册继续验证
129+
通过 JayDeBeApi/JPype 在 Python 进程内调用 JVM。`threadsafety = 1`,模块可被多线程共享,但连接对象不应跨线程共享。建议每个线程从 SQLAlchemy engine 独立获取连接
159130

160-
## 已知限制
131+
## 开发和测试
161132

162-
- GaussDB 集中式不支持 PostgreSQL `ON CONFLICT` upsert 语法。SQLAlchemy PostgreSQL 方言的 `insert(...).on_conflict_do_update()` 会生成 `ON CONFLICT` SQL,当前版本仅声明该限制,不做自动改写。
163-
- M 兼容下 `LIKE` 默认大小写不敏感,符合 MySQL 风格行为;A/B 兼容下 `LIKE` 为大小写敏感。跨兼容模式迁移时需要单独确认查询语义。
164-
- M 兼容下不支持 `INTERSECT` / `EXCEPT` 集合运算;SQLAlchemy 的 `intersect()` / `except_()` 在 M 兼容库上会由数据库返回语法错误。
165-
- M 兼容下 raw SQL `CREATE TEMP TABLE` 不支持,需使用 `CREATE TEMPORARY TABLE`;通过 SQLAlchemy 创建临时表时建议显式使用 `prefixes=["TEMPORARY"]`
133+
```bash
134+
python3 -m venv .venv
135+
. .venv/bin/activate
136+
pip install --upgrade pip
137+
pip install -e ".[test]"
138+
pytest
139+
```
166140

167-
## 并发限制
141+
连接真实 GaussDB 环境跑集成测试:
168142

169-
本项目通过 JayDeBeApi/JPype 在 Python 进程内调用 JVM。`threadsafety = 1`,表示模块可被多线程共享,但连接对象不应跨线程共享。建议每个线程独立从 SQLAlchemy engine 获取连接,并避免在 JVM 首次启动阶段做高并发连接初始化。
143+
```bash
144+
export GAUSSDB_TEST_URL_A='gaussdb+jdbc://user:password@host:port/a_db?sslmode=disable'
145+
export GAUSSDB_TEST_URL_B='gaussdb+jdbc://user:password@host:port/b_db?sslmode=disable'
146+
export GAUSSDB_TEST_URL_M='gaussdb+jdbc://user:password@host:port/m_db?sslmode=disable'
147+
pytest -m integration
148+
```
170149

171150
## 打包
172151

173152
```bash
174-
python -m pip install build
153+
pip install build
175154
python -m build
176155
```
177156

178-
打包后文件会生成在 `dist/` 目录
157+
打包产物在 `dist/` 目录,whl 约 1.5MB(含内置 JDBC 驱动)。
179158

180-
```text
181-
dist/gaussdb_sqlalchemy_driver-0.1.0-py3-none-any.whl
182-
dist/gaussdb_sqlalchemy_driver-0.1.0.tar.gz
159+
## 技术架构
160+
161+
```
162+
Python 应用
163+
164+
SQLAlchemy (ORM / Core)
165+
166+
GaussDB SQLAlchemy Dialect (本驱动)
167+
168+
JayDeBeApi + JPype1
169+
170+
JVM (JRE/JDK 8+)
171+
172+
GaussDB JDBC Driver (内置 jar)
173+
174+
GaussDB 集中式
183175
```
184176

185177
## 开源协议
186178

187-
本项目采用 Apache License 2.0 开源协议发布,详见 [LICENSE](LICENSE)
179+
Apache License 2.0
-19.4 KB
Binary file not shown.
-31.8 KB
Binary file not shown.
1.47 MB
Binary file not shown.
1.52 MB
Binary file not shown.

pyproject.toml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ requires = ["setuptools>=69", "wheel"]
33
build-backend = "setuptools.build_meta"
44

55
[project]
6-
name = "gaussdb-sqlalchemy-driver"
6+
name = "gaussdb-sqlalchemy-python-driver"
77
version = "0.1.0"
88
description = "Lightweight SQLAlchemy JDBC dialect for Huawei GaussDB centralized 505.1."
99
readme = "README.md"
10-
requires-python = ">=3.9"
10+
requires-python = ">=3.8"
1111
license = "Apache-2.0"
1212
authors = [{ name = "GaussDB Python Driver Contributors" }]
1313
keywords = ["gaussdb", "sqlalchemy", "database", "driver", "windows"]
@@ -17,6 +17,7 @@ classifiers = [
1717
"Operating System :: Microsoft :: Windows",
1818
"Operating System :: POSIX",
1919
"Programming Language :: Python :: 3 :: Only",
20+
"Programming Language :: Python :: 3.8",
2021
"Programming Language :: Python :: 3.9",
2122
"Programming Language :: Python :: 3.10",
2223
"Programming Language :: Python :: 3.11",
@@ -38,8 +39,8 @@ test = [
3839
]
3940

4041
[project.urls]
41-
Homepage = "https://github.com/jarrenL/GaussDB-Python-Driver"
42-
Issues = "https://github.com/jarrenL/GaussDB-Python-Driver/issues"
42+
Homepage = "https://github.com/jarrenL/GaussDB-SQLAlchemy-Python-Driver"
43+
Issues = "https://github.com/jarrenL/GaussDB-SQLAlchemy-Python-Driver/issues"
4344

4445
[project.entry-points."sqlalchemy.dialects"]
4546
gaussdb = "gaussdb_sqlalchemy.jdbc:GaussDBDialect_jdbc"
@@ -48,6 +49,9 @@ gaussdb = "gaussdb_sqlalchemy.jdbc:GaussDBDialect_jdbc"
4849
[tool.setuptools.packages.find]
4950
where = ["src"]
5051

52+
[tool.setuptools.package-data]
53+
gaussdb_sqlalchemy = ["gaussdbjdbc.jar"]
54+
5155
[tool.pytest.ini_options]
5256
testpaths = ["tests"]
5357
pythonpath = ["src"]

0 commit comments

Comments
 (0)