Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
b7844a9
feat(postgres): add named-query CLI subcommand
vistart Apr 18, 2026
57e666d
feat(backend): add named-procedure CLI subcommand
vistart Apr 19, 2026
a6db264
Add CLI tests for named-query and named-procedure subcommands
vistart Apr 19, 2026
8f76979
feat(postgres): use custom epilog for named-query/procedure CLI
vistart Apr 20, 2026
8511435
feat(backend): add ConcurrencyAware for PostgreSQL
vistart Apr 20, 2026
73500dc
test(backend): add ConcurrencyAware protocol tests for PostgreSQL
vistart Apr 20, 2026
67350c0
fix: update async marker for pytest-asyncio 1.3.0 compatibility
vistart Apr 20, 2026
069b75c
Add CreateExtensionExpression and DropExtensionExpression DDL classes
vistart Apr 21, 2026
a6782ef
Add multi-arch PostgreSQL image with all extensions
vistart Apr 21, 2026
069594d
test(postgres): add protocol conformance tests
vistart Apr 22, 2026
4d9c894
fix(tests): remove AsyncIntrospectionSupport exclusion
vistart Apr 22, 2026
d3c36d3
refactor(backend): move threadsafety to PostgresBackendMixin
vistart Apr 23, 2026
ccbe149
feat(named-connection): unify handle_info config resolution and add t…
vistart Apr 23, 2026
a090395
fix(tests): remove __init__.py from named_connection test directory
vistart Apr 23, 2026
8984c70
feat(extensions): enhance PostgreSQL extension detection with availab…
vistart Apr 23, 2026
182acd3
fix(extensions): detect available extensions from pg_available_extens…
vistart Apr 23, 2026
932ce5a
feat(introspect): sort extensions by name
vistart Apr 23, 2026
4f264db
feat(extensions): add Protocol and Mixin for 17 new PostgreSQL extens…
vistart Apr 23, 2026
8702198
feat(examples): add citext extension example
vistart Apr 23, 2026
291cebf
feat(examples): add fuzzystrmatch and citext extension examples
vistart Apr 23, 2026
fac2728
feat(examples): add uuid_ossp and hstore extension examples
vistart Apr 23, 2026
d927af1
feat: simplify named connection API and add PostgreSQL CLI tests
vistart Apr 24, 2026
fb7fb93
feat: integrate named-connection subcommand into PostgreSQL CLI
vistart Apr 24, 2026
9c03be3
feat: add PostgreSQL named connection examples
vistart Apr 24, 2026
6d68ebc
fix(extensions): align Protocol and Mixin interfaces for 4 extensions
vistart Apr 24, 2026
cf8d5dc
feat(extensions): supplement format_* methods and Protocol signatures…
vistart Apr 24, 2026
3298c88
test(extensions): add test skip mechanism and unit tests for 20 exten…
vistart Apr 24, 2026
d71acd2
test(extensions): add integration tests for 8 extensions
vistart Apr 24, 2026
962a2de
feat(examples): add 8 extension usage examples
vistart Apr 24, 2026
1ac6a4c
feat(extensions): add postgis_raster and pgrouting Protocol/Mixin, up…
vistart Apr 24, 2026
d36e8ef
refactor(examples): replace raw SQL with expression API in extension …
vistart Apr 24, 2026
988a382
fix(postgres): remove RawSQLExpression from extension examples and fi…
vistart Apr 24, 2026
4d1b13e
refactor(postgres): modularize CLI from monolithic __main__.py to cli…
vistart Apr 24, 2026
ba9bae2
fix(postgres): remove tests. prefix from module paths, add tests to P…
vistart Apr 26, 2026
91d6f56
refactor(backend): align expression system with three architectural p…
vistart Apr 26, 2026
24da7a6
fix(tests): correct UUID v1 regex pattern to match standard 8-4-4-4-1…
vistart Apr 26, 2026
6a81320
fix(tests): add derivation pairs to protocol non-overlap exclusions
vistart Apr 26, 2026
531aba2
fix(protocols): add @runtime_checkable to PostgresAdvisoryLockSupport…
vistart Apr 26, 2026
2c18e96
fix(backend): convert ? placeholders to %s for psycopg in _prepare_sq…
vistart Apr 26, 2026
9c6030c
refactor(backend): remove _convert_qmark_to_format fallback from Post…
vistart Apr 26, 2026
c02c936
fix(dialect): handle base ForUpdateClause without strength attribute …
vistart Apr 26, 2026
5ec318d
ci: install testsuite from git branch release/v1.0.0.dev12
vistart Apr 26, 2026
0591a1c
refactor(backend): use in_transaction property instead of direct _tra…
vistart Apr 26, 2026
ab6fdb8
ci: install rhosocial-activerecord from git branch release/v1.0.0.dev25
vistart Apr 27, 2026
a429a51
ci: add postgres-exts service container for extension testing
vistart Apr 27, 2026
1bb15ca
chore: add changelog fragment for PR #32
vistart Apr 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,19 @@ jobs:
POSTGRES_PASSWORD: password
ports:
- 5432:5432
# Options to wait for postgres to be healthy before starting the job
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
postgres-exts:
image: vistart/postgres-exts:${{ matrix.postgres-version }}
env:
POSTGRES_DB: test_db
POSTGRES_USER: root
POSTGRES_PASSWORD: password
ports:
- 5433:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
Expand All @@ -65,10 +77,10 @@ jobs:
pip install -r requirements.txt
pip install -r requirements-dev.txt

- name: Install activerecord and testsuite from PyPI
- name: Install activerecord and testsuite from PyPI/git
run: |
pip install rhosocial-activerecord==1.0.0.dev24
pip install rhosocial-activerecord-testsuite==1.0.0.dev11
pip install git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev25
pip install git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev12

- name: Create postgres scenario config
run: |
Expand All @@ -80,6 +92,12 @@ jobs:
database: test_db
username: root
password: password
postgres_exts:
host: 127.0.0.1
port: 5433
database: test_db
username: root
password: password
EOF
echo "POSTGRES_SCENARIOS_CONFIG_PATH=$(pwd)/postgres_scenarios.yaml" >> $GITHUB_ENV

Expand All @@ -95,17 +113,22 @@ jobs:
sleep 2
done
echo "postgres is ready!"
until pg_isready -h 127.0.0.1 -p 5433 -U root; do
echo "Waiting for postgres-exts..."
sleep 2
done
echo "postgres-exts is ready!"

- name: Run tests (skip for postgres 18)
if: matrix.postgres-version != '18'
run: |
export PYTHONPATH=src
export PYTHONPATH=src:tests
python -m pytest tests/ --tb=short

- name: Run tests with coverage (only for postgres 18)
if: matrix.postgres-version == '18'
run: |
export PYTHONPATH=src
export PYTHONPATH=src:tests
pip install codecov
coverage run --source=src -m pytest tests/ --tb=short
coverage xml
Expand Down
1 change: 1 addition & 0 deletions changelog.d/32.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added named query and named procedure CLI subcommands for PostgreSQL backend. Added ConcurrencyAware protocol implementation for PostgreSQL. Added named connection support with PostgreSQL CLI integration. Added comprehensive extension support with Protocol/Mixin definitions for 29 PostgreSQL extensions, CreateExtensionExpression/DropExtensionExpression DDL classes, and extension availability detection.
1 change: 1 addition & 0 deletions changelog.d/32.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Aligned expression system with three architectural principles. Modularized CLI from monolithic __main__.py to cli/ subpackage. Moved threadsafety to PostgresBackendMixin. Removed _convert_qmark_to_format fallback (now uses proper dialect placeholder conversion). Changed CI to install rhosocial-activerecord from git branch release/v1.0.0.dev25. Added postgres-exts service container for extension testing in CI.
1 change: 1 addition & 0 deletions changelog.d/32.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed ? → %s placeholder conversion for psycopg in _prepare_sql_and_params. Fixed ForUpdateClause handling without strength attribute. Fixed @runtime_checkable missing on PostgresAdvisoryLockSupport and PostgresMultirangeSupport. Fixed UUID v1 regex pattern to match standard 8-4-4-4-12 format. Fixed async marker for pytest-asyncio 1.3.0 compatibility.
81 changes: 81 additions & 0 deletions docker/postgres-all-ext/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# docker/postgres-all-ext/Dockerfile
# Multi-arch Dockerfile for PostgreSQL with all extensions
#
# Supported architectures: linux/amd64, linux/arm64, linux/ppc64le, linux/s390x
# Supported PostgreSQL versions: 14, 15, 16, 17, 18
#
# Usage:
# docker build -t postgres-all-ext:16 .
# docker run -e POSTGRES_PASSWORD=secret postgres-all-ext:16
#
# Build arguments:
# PG_VERSION: PostgreSQL version (default: 16)
# POSTGIS_VERSION: PostGIS version (default: 3.4)
# PGVECTOR_VERSION: pgvector version (default: 0.8.0)
#
# Build example:
# docker build --build-arg PG_VERSION=16 -t postgres-all-ext:16 .
#

ARG PG_VERSION=16
FROM postgres:${PG_VERSION}-bookworm

LABEL maintainer="rhosocial"
LABEL org.opencontainers.image.description="PostgreSQL with all common extensions for testing"
LABEL org.opencontainers.image.source="https://github.com/rhosocial/python-activerecord-postgres"

# Build arguments
ARG PG_VERSION
ARG POSTGIS_VERSION=3.4
ARG PGVECTOR_VERSION=0.8.0

# Environment variables
ENV PG_MAJOR=${PG_VERSION} \
POSTGIS_MAJOR=${POSTGIS_VERSION} \
PGVECTOR_VERSION=${PGVECTOR_VERSION}

# Install all extensions
# Note: bookworm is Debian-based with multi-arch support
RUN apt-get update && apt-get install -y --no-install-recommends \
# PostGIS (spatial database extension)
postgresql-${PG_MAJOR}-postgis-${POSTGIS_MAJOR} \
postgresql-${PG_MAJOR}-postgis-${POSTGIS_MAJOR}-scripts \
\
# pgvector (vector similarity search)
postgresql-${PG_MAJOR}-pgvector \
\
# earthdistance (great-circle distance calculations)
# Requires cube extension as dependency
postgresql-${PG_MAJOR}-cube \
postgresql-${PG_MAJOR}-earthdistance \
\
# Additional contrib extensions for comprehensive testing
postgresql-${PG_MAJOR}-uuid-ossp \
postgresql-${PG_MAJOR}-pg-trgm \
postgresql-${PG_MAJOR}-hstore \
\
# Utilities
ca-certificates \
curl \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean

# Copy initialization scripts
COPY docker-entrypoint-initdb.d/ /docker-entrypoint-initdb.d/
RUN chmod 755 /docker-entrypoint-initdb.d/*.sh /docker-entrypoint-initdb.d/*.sql 2>/dev/null || true

# Expose default port
EXPOSE 5432

# Default environment variables
ENV POSTGRES_DB=test_db \
POSTGRES_USER=root \
POSTGRES_PASSWORD=password

# Health check
HEALTHCHECK --interval=10s --timeout=5s --retries=5 \
CMD pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB} || exit 1

# Use default postgres entrypoint
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["postgres"]
172 changes: 172 additions & 0 deletions docker/postgres-all-ext/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# PostgreSQL with All Extensions

多架构 PostgreSQL Docker 镜像,包含所有常见扩展,用于测试 python-activerecord-postgres 项目。

## 支持的架构

- linux/amd64
- linux/arm64
- linux/ppc64le
- linux/s390x

## 支持的 PostgreSQL 版本

- PostgreSQL 14
- PostgreSQL 15
- PostgreSQL 16
- PostgreSQL 17
- PostgreSQL 18

## 预装的扩展

### 内置扩展 (contrib)

| 扩展 | 版本 | 说明 |
|-------|-----|------|
| uuid-ossp | 1.1 | UUID 生成函数 |
| pgcrypto | 1.3/1.4 | 加密函数 |
| ltree | 1.1~1.3 | 层级数据结构 |
| intarray | 1.2~1.5 | 整数数组操作符 |
| tablefunc | 1.0 | 表函数 (crosstab) |
| pg_trgm | 1.3~1.6 | 三元组相似度 |
| hstore | 1.4~1.8 | 键值存储 |
| cube | 1.2~1.5 | 多维立方体 |
| earthdistance | 1.1~1.3 | 地球距离 |
| pg_stat_statements | 1.4~1.12 | 查询统计 |

### 第三方扩展

| 扩展 | 版本 | 说明 |
|-------|-----|------|
| postgis | 3.4 | 空间数据库 |
| postgis_topology | 3.4 | PostGIS 拓扑 |
| postgis_tiger_geocoder | 3.4 | 地理编码 |
| vector | 0.8.0 | 向量相似度搜索 |

## 快速开始

### 使用预构建镜像

```bash
# 运行容器
docker run -d \
--name postgres-all-ext \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_DB=test_db \
-p 5432:5432 \
postgres:16

# 或者使用 docker-compose
docker compose up -d
```

### 构建本地镜像

```bash
# 进入目录
cd docker/postgres-all-ext

# 构建默认版本 (16)
./build.sh

# 构建所有版本
./build.sh all

# 构建特定版本
./build.sh 16
```

## 环境变量

| 变量 | 默认值 | 说明 |
|-----|-------|------|
| POSTGRES_USER | root | 数据库用户 |
| POSTGRES_PASSWORD | password | 数据库密码 |
| POSTGRES_DB | test_db | 数据库名称 |

## 验证扩展

```bash
# 连接数据库
docker exec -it postgres-all-ext psql -U root -d test_db

# 查看已安装的扩展
SELECT extname, extversion FROM pg_extension ORDER BY extname;

# 测试 postgis
SELECT postgis_version();

# 测试 pgvector
SELECT '[-1,0,1]'::vector;

# 测试 pg_trgm
SELECT similarity('hello', 'helo');
```

## 构建参数

| 参数 | 默认值 | 说明 |
|-----|-------|------|
| PG_VERSION | 16 | PostgreSQL 主版本 |
| POSTGIS_VERSION | 3.4 | PostGIS 版本 |
| PGVECTOR_VERSION | 0.8.0 | pgvector 版本 |

## 目录结构

```
docker/postgres-all-ext/
├── Dockerfile # 多架构构建文件
├── docker-compose.yml # Compose 配置
├── build.sh # 构建脚本
├── README.md # 本文件
└── docker-entrypoint-initdb.d/
└── init-extensions.sh # 扩展初始化脚本
```

## GitHub Actions

可以使用 GitHub Actions 构建多架构镜像:

```yaml
# .github/workflows/build.yml
name: Build PostgreSQL Images

on:
push:
branches:
- main

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
pg_version: [14, 15, 16, 17, 18]
steps:
- uses: actions/checkout@v4
- uses: docker/build-push-action@v5
with:
context: docker/postgres-all-ext
push: false
tags: postgres-all-ext:${{ matrix.pg_version }}
build-args: |
PG_VERSION=${{ matrix.pg_version }}
```

## 注意事项

1. **架构支持**: Debian bookworm 原生支持 amd64, arm64; ppc64le 和 s390x 需要额外配置
2. **版本兼容性**: PostGIS 3.4 支持 PostgreSQL 13-16; PostgreSQL 17+ 需要 PostGIS 3.5+
3. **资源限制**: 建议至少 2GB 内存
4. **数据持久化**: 使用 docker volume 持久化数据

## License

继承 PostgreSQL 和各扩展的许可证

## 参考

- [PostgreSQL Docker](https://github.com/docker-library/postgres)
- [PostGIS Docker](https://github.com/postgis/docker-postgis)
- [pgvector](https://github.com/pgvector/pgvector)
- [PostgreSQL contrib](https://www.postgresql.org/docs/current/contrib.html)
56 changes: 56 additions & 0 deletions docker/postgres-all-ext/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/bash
# docker/postgres-all-ext/build.sh
#
# Build PostgreSQL images with all extensions for multiple versions
#
# Usage:
# ./build.sh [version]
# ./build.sh all
# ./build.sh 14 15 16
#

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BUILD_DIR="$SCRIPT_DIR"

# Default versions
VERSIONS=${1:-"14 15 16 17 18"}

# Build for all versions
build_all() {
echo "Building PostgreSQL images for versions: $VERSIONS"
for ver in $VERSIONS; do
echo "Building postgres-all-ext:$ver ..."
docker build \
--build-arg PG_VERSION=$ver \
--build-arg POSTGIS_VERSION=3.4 \
-t postgres-all-ext:$ver \
-f Dockerfile \
.
echo "Built postgres-all-ext:$ver successfully"
done
}

# Main
case "$1" in
all)
VERSIONS="14 15 16 17 18"
build_all
;;
help|--help|-h)
echo "Usage: $0 [versions|all]"
echo " $0 # Build default versions (14 15 16 17 18)"
echo " $0 all # Build all versions"
echo " $0 16 # Build specific version"
echo " $0 14 15 16 # Build multiple versions"
;;
*)
if [ $# -eq 0 ]; then
VERSIONS="14 15 16 17 18"
fi
build_all
;;
esac

echo "Done!"
Loading
Loading