Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
1607dff
feat(db): ODBC 后端 —— 第四个后端,对着的是接口而不是某一种库(1.7.1-dev)
Antruly Oct 15, 2026
03084be
fix(db): ODBC 按实测改六处,并把它接进共用套件(1.7.1-dev)
Antruly Oct 15, 2026
f40700d
feat(db): ODBC 也接上 UVCPP_DB_RUNTIME_LOAD —— 驱动管理器就是它的"客户端库"(1.7.1-dev)
Antruly Oct 15, 2026
57c93d8
fix(db): ODBC 头在 Windows 上要先来 <windows.h>(1.7.1-dev)
Antruly Oct 15, 2026
dd361a8
Merge master(1.7.2-dev)进 feature/db-odbc
Antruly Oct 16, 2026
449abdc
build(db): 六条打包腿显式开 ODBC 并断言宏(1.7.2-dev)
Antruly Oct 16, 2026
1da3188
test(db): 驱动管理器不在时回 NO_DRIVER 的用例(1.7.2-dev)
Antruly Oct 16, 2026
c84f554
docs(db): ODBC 进主干后的口径、版本号与打包那一节(1.7.2-dev)
Antruly Oct 16, 2026
4463ef4
fix(db): 两个 ODBC 新文件补 UTF-8 BOM(1.7.2-dev)
Antruly Oct 16, 2026
805613f
fix(build): `odbc32.dll` 进"Windows 自带模块"表,默认档在 Windows 上才打得出包(1.7.2-dev)
Antruly Oct 16, 2026
ac10a6d
Merge remote-tracking branch 'origin/master' into feature/db-odbc
Antruly Oct 16, 2026
630fd70
fix(ci): Linux 两条发布腿的 ODBC 头判据改成"编一次",不再要求 unixodbc.h 存在(1.7.2-dev)
Antruly Oct 16, 2026
c61b992
fix(db): ODBC 后端在 mingw 上编不过 —— unixODBC 补的 WCHAR 与 winnt.h 硬冲突(1.7.2…
Antruly Oct 16, 2026
aaded85
Merge remote-tracking branch 'origin/master' into feature/db-odbc
Antruly Oct 16, 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
110 changes: 110 additions & 0 deletions .github/scripts/win-odbc-headers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env bash
# ---------------------------------------------------------------------------
# 把 Windows SDK 里那份 **ODBC 头目录**(`<SDK>/Include/<ver>/um`)找出来,打到
# stdout 上(只有路径这一行;诊断全部走 stderr,因为这个脚本的调用方式是
# `ODBC_INC=$(bash .github/scripts/win-odbc-headers.sh)`)。
#
# 给谁用:`release.yml` 的两条 **MSVC** 腿(msvc-x64 / msvc-arm64)。它们要
# `-DUVCPP_DB_ODBC_INCLUDE_DIR=` 指到一份 `sql.h` 上 —— db 的第四个后端(ODBC)
# 从 1.7.2 起进发布包,而它**默认 ON、找不到头只 WARNING 一句就自己关掉**
# (`CMakeLists.txt` 里那段 `message(WARNING)` + `set(... OFF)` 是普通变量赋值 ⇒
# `CMakeCache.txt` 里照旧写着 ON)。所以"这条腿有没有弄到头"这件事**只能**从生成的
# `uvcpp_config.h` 里看出来,而下面这一步必须在"取不到"时**当场红**,不能静默过去
# —— 静默过去就是一个少一个后端的包,而且它会一路走到发版。
#
# 为什么是 SDK 那份、而不是像两条 MinGW 腿那样用 MSYS2 的 unixODBC:
#
# · 微软的 ODBC 头**本来就是 SDK 的一部分**(`sql.h`/`sqlext.h`/`sqltypes.h`
# 都在 `Include/<ver>/um/` 下),随工具链一起装、版本跟着工具链走,不需要
# 网络、不需要解包、也不引入第二种头来源;
# · 这份头**已经在这个后端上验过**:wlzaweb 的 CI(`.github/workflows/release-win.yml`)
# 里 libuvcpp 的 ODBC 后端就是在 SDK 头上编出来的,并且连上真 SQL Server
# (LocalDB + ODBC Driver 17)跑通了业务口径 —— 那套流程里找头的那段逻辑就是
# 下面这段,这次是把它从那边搬过来。
# · 两条 MinGW 腿不走这条路:SDK 的头是给 MSVC 的(`__declspec`、SAL、`#pragma`),
# 混进 mingw 工具链是拿一整套没人试过的组合去赌。它们用 unixODBC 那份(上游给
# mingw 编的就是它),运行期反正加载的都是系统 `odbc32.dll`,两种头在这个后端
# 里是等价的(`src/db/uvcpp_db_odbc.cpp` 头部那条"不假设 `SQLWCHAR` 宽度"就是
# 为这件事写的)。
#
# **真正承重的是"挑哪一版 SDK"这一句,别把它改成字典序。** 这是实测出来的,不是
# 推断:`ls` 的字典序会把 `10.0.17763.0`(第一个 compat-only 的 SDK)排在最前,
# 于是 `um` 指向一份老 SDK,而工具箱里那份 `<windows.h>`/`winnt.h` 来自新 SDK ——
# 两边混着用,报出来的是 `oaidl.h` / `propidlbase.h` / `sqltypes.h` 里成百条的
# `C4430` / `C2144`(实测一次是 283 + 166 条),指着 `typedef INT64 SQLLEN;` 这种行,
# 看上去像 ODBC 或 SDK 坏了,其实只是版本对不上。**默认 SDK(VS 生成器自己挑的那份)
# 就是版本号最大的那个**,所以"按版本号取最大"正是"和我们正在用的工具链同一份"。
#
# `-V`(GNU sort 的版本排序)在 Git for Windows 的 `sort` 上有,两条 MSVC 腿的
# `shell: bash` 就是它。
#
# 判据落在**文件在不在**(与 `win-client-headers.sh` / `win-openssl-deps.sh` 同一
# 条规矩),不落在任何命令的退出码上。找不到时把"真实目录长什么样"打出来再退 1 ——
# 镜像升级换 SDK 是常事,那时候要能一眼看出是路径变了还是真没有。
#
# 可选的命令行参数:给一个或多个"搜索根"(默认是两张镜像上的 `Windows Kits/10/Include`)。
# 参数只为**本机自测**存在(在 Linux 上造两棵假树,验证"按版本号取最大"这一条),
# CI 里不传。
# ---------------------------------------------------------------------------
set -u

if [ "$#" -gt 0 ]; then
ROOTS=("$@")
else
ROOTS=(
"/c/Program Files (x86)/Windows Kits/10/Include"
"/c/Program Files/Windows Kits/10/Include"
)
fi

cands=""
for root in "${ROOTS[@]}"; do
[ -d "$root" ] || continue
for hdr in "$root"/*/um/sql.h; do
# 没有匹配时 glob 会原样留着(`set -u` 下也不会报),所以这里要判一下。
[ -f "$hdr" ] || continue
cands="${cands}$(basename "$(dirname "$(dirname "$hdr")")") $(dirname "$hdr")
"
done
done

if [ -z "$cands" ]; then
echo "::error title=win-no-odbc-headers::在 SDK 里找不到 sql.h —— db 的 ODBC 后端会静默降级(生成头里 UVCPP_DB_ODBC_ENABLE=0),包少一个后端"
echo "找过的根(这些目录现在长这样):" >&2
for root in "${ROOTS[@]}"; do
echo "--- $root" >&2
if [ -d "$root" ]; then
ls -1 "$root" >&2 || true
echo " 该根下递归命中的 sql.h:" >&2
find "$root" -name 'sql.h' 2>/dev/null | sed 's/^/ /' >&2 || true
else
echo " (这个目录不存在)" >&2
fi
done
exit 1
fi

# 按版本号取最大(不是字典序 —— 理由见文件头)。`cut -f1` 之后用 `sort -V` 排的是
# 版本号本身,再把对应的那一行取回来;这样同一个版本号出现两次也无所谓。
ver=$(printf '%s' "$cands" | cut -f1 | sort -V | tail -1)
dir=$(printf '%s' "$cands" | awk -F'\t' -v v="$ver" '$1==v {print $2; exit}')

if [ ! -f "$dir/sql.h" ]; then
echo "::error title=win-odbc-headers-race::挑出来的目录里没有 sql.h:$dir"
printf '%s' "$cands" >&2
exit 1
fi

echo "候选(SDK 版本 → um 目录),取版本号最大的那个:" >&2
printf '%s' "$cands" | sed 's/^/ /' >&2
echo "选中: SDK $ver → $dir" >&2

# 路径里有空格与括号(`Program Files (x86)`),所以给 CMake 的是 **Windows 形式**
# 且**带引号**的一份。MSVC 腿的 shell 是 Git Bash(有 cygpath);万一没有,
# 就退成原样的 POSIX 形式 —— CMake 在 Git Bash 下也认 `/c/...` 这种写法,只是
# 显式给 Windows 形式更稳(也更好在日志里读)。
if command -v cygpath >/dev/null 2>&1; then
cygpath -m "$dir"
else
echo "$dir"
fi
4 changes: 2 additions & 2 deletions .github/workflows/ci-linux-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ jobs:
# 模块关掉时它们被 `tests/functional/CMakeLists.txt` 的 glob+FILTER 摘掉,
# 而 ctest 报 "100% tests passed" 时并不会说"少了几条"。
#
# **不需要任何新包**:pugixml 走 FetchContent(`CMakeLists.txt:1667`),
# **不需要任何新包**:pugixml 走 FetchContent(`CMakeLists.txt:1736`),
# 装包表与 `web` 那一格逐字相同 —— 这样两边红绿不同只可能归因到那个开关。
# 四个门禁串见 doc/ci-guide.md §5。
- feature: wsdl
Expand Down Expand Up @@ -139,7 +139,7 @@ jobs:
# nlohmann 那侧照编照跑(`web_app_request_func` 里深度预扫描的五条断言
# 也在),yyjson 那侧的新用例才拿得到对照物。
#
# **不需要任何新包**:yyjson 走 FetchContent(`CMakeLists.txt:1727`,
# **不需要任何新包**:yyjson 走 FetchContent(`CMakeLists.txt:1796`,
# `GIT_TAG` 钉在 `YYJSON_VERSION`),装包表与 `web` 那一格逐字相同 ——
# 这样两边红绿不同只可能归因到那个开关。
# 四个门禁串见 doc/ci-guide.md §5。
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
# 与 wsdl 不同:macOS **没有** wsdl 格(§1 的"未覆盖的格"表里那一行写的
# 是"不发版、风险低"),而 yyjson 这一格加得起 —— 它不需要任何新包。
#
# yyjson 走 FetchContent(根 `CMakeLists.txt:1727`,`GIT_TAG` 钉在
# yyjson 走 FetchContent(根 `CMakeLists.txt:1796`,`GIT_TAG` 钉在
# `YYJSON_VERSION`),**不需要新包**;装包表与 `web` 逐字相同 —— 这样两边
# 红绿不同只可能归因到那个开关。
# 四个门禁串见 doc/ci-guide.md §5。
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci-mingw64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ jobs:
# 不带 preset ⇒ 这个开关默认 OFF ⇒ `find_library` 在 MSYS2 里撞上
# C:/msys64/mingw64/lib/libuv.dll.a(runner 镜像自带 libuv)⇒ 链成
# 共享库,产物依赖 `libuv-1.dll`(MSYS2 那份的 DLL 名带 -1)。
# 注意 `BUILD_SHARED_LIBS` 在这一路上救不了场:CMakeLists.txt:1404-1404 判的是
# 注意 `BUILD_SHARED_LIBS` 在这一路上救不了场:CMakeLists.txt:1473-1473 判的是
# `TARGET uv_a`,而 find_library 给的是一个**路径**,不是 target,
# 所以那个分支根本进不去。
#
# ② -DBUILD_SHARED_LIBS=OFF —— 管 llhttp(根 CMakeLists.txt:6 默认 ON ⇒
# llhttp_shared ⇒ 依赖 libllhttp.dll)。它不管 uvcpp 自己
# (CMakeLists.txt:1915-1915 是显式的 `add_library(uvcpp SHARED ...)`)。
# (CMakeLists.txt:1984-1984 是显式的 `add_library(uvcpp SHARED ...)`)。
# 本地 A/B 过:OFF 时链接行是 `_deps/llhttp-build/libllhttp.a`,ON 时是
# `libllhttp.dll.a`。装到 FetchContent 的 libuv 上时它顺带也管 libuv
# (708 行挑 `uv_a`),但那一路在 CI 上本来就走不到。
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci-windows-msvc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
# **发版那一刻** —— 而 release.yml 的 msvc-x64 / msvc-arm64 两条腿都开着
# 它。这一格就是那两条腿在 push/PR 阶段的替身。
#
# pugixml 走 FetchContent(根 `CMakeLists.txt:1667`,`GIT_TAG` 钉在
# pugixml 走 FetchContent(根 `CMakeLists.txt:1736`,`GIT_TAG` 钉在
# `PUGIXML_VERSION`),**不需要新包**;它与 zlib 同一个形状,所以这一格
# 的装包需求与 `web` 逐字相同。
# 四个门禁串见 doc/ci-guide.md §5。
Expand Down Expand Up @@ -95,7 +95,7 @@ jobs:
# nlohmann 再比 `==`」—— 平台间差异正是在这种地方现形。
# (yaml 里这段 `-D` 之所以放在块序列里、不折成一行,见 §1。)
#
# yyjson 走 FetchContent(根 `CMakeLists.txt:1727`,`GIT_TAG` 钉在
# yyjson 走 FetchContent(根 `CMakeLists.txt:1796`,`GIT_TAG` 钉在
# `YYJSON_VERSION`),**不需要新包**;它与 zlib 同一个形状,所以这一格
# 的装包需求与 `web` 逐字相同。
# 四个门禁串见 doc/ci-guide.md §5。
Expand Down Expand Up @@ -340,7 +340,7 @@ jobs:
run: |
case "${{ matrix.feature }}" in
# wsdl 也在这一组:pugixml 走 FetchContent,与 zlib 一样不是系统依赖。
# yyjson 同理(`CMakeLists.txt:1727` 的 FetchContent)。
# yyjson 同理(`CMakeLists.txt:1796` 的 FetchContent)。
# db 也是:它的 SQLite 是**从源码编**的(`UVCPP_DB_SQLITE_FROM_SOURCE`),
# 所以 Windows 上不需要任何 sqlite 包 —— 这一格一个系统依赖都没有,
# 别把它塞进 win-openssl-deps.sh(那是 OpenSSL 专用的)。
Expand Down
Loading
Loading