Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/release_publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
id: deb-package-cache-key
shell: bash
run: |
echo "prefix=ubuntu-24.04-deb-packages-${{ hashFiles('CMakeLists.txt', 'cmake/**', 'contrib/**', 'include/**', 'library/**', 'plugins/**', 'scripts/build_cpack_deb_packages.sh', 'scripts/generate-debian-directory.sh', 'scripts/googleapis_deb/**', 'src/**', 'third_party/api-common-protos/**', 'tools/**', 'util/**') }}" >> "$GITHUB_OUTPUT"
echo "prefix=ubuntu-24.04-deb-packages-${{ hashFiles('CMakeLists.txt', 'cmake/**', 'contrib/**', 'include/**', 'library/**', 'odbc/**', 'plugins/**', 'scripts/build_cpack_deb_packages.sh', 'scripts/generate-debian-directory.sh', 'scripts/googleapis_deb/**', 'src/**', 'third_party/api-common-protos/**', 'tools/**', 'util/**') }}" >> "$GITHUB_OUTPUT"

- name: Restore Debian package build cache
uses: actions/cache/restore@v4
Expand Down
17 changes: 16 additions & 1 deletion .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
types: [opened, synchronize, reopened, ready_for_review]
branches:
- main
- odbc-driver-feature
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
Expand Down Expand Up @@ -54,9 +55,15 @@ jobs:
with:
compiler: ${{ matrix.compiler }}
- name: Test
if: github.event_name != 'pull_request' || github.base_ref == 'main'
shell: bash
run: |
ctest -j$(nproc) --preset unit
- name: Test ODBC
if: github.event_name == 'pull_request' && github.base_ref == 'odbc-driver-feature'
shell: bash
run: |
ctest --test-dir build/odbc/tests/unit -j$(nproc) --output-on-failure
- name: Package integration build
shell: bash
run: |
Expand Down Expand Up @@ -132,6 +139,7 @@ jobs:
tar -C build -xzf "integration-build-${{ matrix.compiler }}.tar.gz"
tar -C "$HOME" -xzf "integration-deps-${{ matrix.compiler }}.tar.gz"
- name: Test
if: github.event_name != 'pull_request' || github.base_ref == 'main'
shell: bash
run: |
IAM_REGEX='^(DriverAuth|TMetadataFixture|TJwtIamFixture|TOAuthIamFixture|OAuth_WithFacility)\.'
Expand All @@ -144,8 +152,15 @@ jobs:
./.github/scripts/run_iam_integration_tests.sh
;;
esac
- name: Test ODBC
if: github.event_name == 'pull_request' && github.base_ref == 'odbc-driver-feature'
shell: bash
run: |
YDB_VERSION=${{ matrix.ydb-version }} \
ctest --test-dir build/odbc/tests/integration -j2 --output-on-failure

test-install:
if: github.event_name != 'pull_request' || github.base_ref == 'main'
name: "Test CMake Install"
concurrency:
group: test-install-${{ github.ref }}-${{ matrix.compiler }}
Expand Down Expand Up @@ -228,7 +243,7 @@ jobs:
id: deb-package-cache-key
shell: bash
run: |
echo "prefix=ubuntu-24.04-deb-packages-${{ hashFiles('CMakeLists.txt', 'cmake/**', 'contrib/**', 'include/**', 'library/**', 'plugins/**', 'scripts/build_cpack_deb_packages.sh', 'scripts/generate-debian-directory.sh', 'scripts/googleapis_deb/**', 'src/**', 'third_party/api-common-protos/**', 'tools/**', 'util/**') }}" >> "$GITHUB_OUTPUT"
echo "prefix=ubuntu-24.04-deb-packages-${{ hashFiles('CMakeLists.txt', 'cmake/**', 'contrib/**', 'include/**', 'library/**', 'odbc/**', 'plugins/**', 'scripts/build_cpack_deb_packages.sh', 'scripts/generate-debian-directory.sh', 'scripts/googleapis_deb/**', 'src/**', 'third_party/api-common-protos/**', 'tools/**', 'util/**') }}" >> "$GITHUB_OUTPUT"

- name: Validate dpkg-buildpackage
shell: bash
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/warmup_cache.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ jobs:
id: deb-package-cache-key
shell: bash
run: |
echo "prefix=ubuntu-24.04-deb-packages-${{ hashFiles('CMakeLists.txt', 'cmake/**', 'contrib/**', 'include/**', 'library/**', 'plugins/**', 'scripts/build_cpack_deb_packages.sh', 'scripts/generate-debian-directory.sh', 'scripts/googleapis_deb/**', 'src/**', 'third_party/api-common-protos/**', 'tools/**', 'util/**') }}" >> "$GITHUB_OUTPUT"
echo "prefix=ubuntu-24.04-deb-packages-${{ hashFiles('CMakeLists.txt', 'cmake/**', 'contrib/**', 'include/**', 'library/**', 'odbc/**', 'plugins/**', 'scripts/build_cpack_deb_packages.sh', 'scripts/generate-debian-directory.sh', 'scripts/googleapis_deb/**', 'src/**', 'third_party/api-common-protos/**', 'tools/**', 'util/**') }}" >> "$GITHUB_OUTPUT"
- name: Restore Debian package build cache
id: deb-package-cache
uses: actions/cache/restore@v4
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,17 @@ wget "${BASE}/libydb-cpp-dev_${TAG#v}_amd64.deb"
wget "${BASE}/libydb-cpp-iam-dev_${TAG#v}_amd64.deb"
wget "${BASE}/libydb-cpp-otel-metrics-dev_${TAG#v}_amd64.deb"
wget "${BASE}/libydb-cpp-otel-tracing-dev_${TAG#v}_amd64.deb"
# Optional ODBC driver:
wget "${BASE}/ydb-odbc_${TAG#v}_amd64.deb"

sudo apt-get update
sudo apt-get install -y \
./yandex-googleapis-api-common-protos-*.deb \
./libydb-cpp-dev_*.deb ./libydb-cpp-iam-dev_*.deb \
./libydb-cpp-otel-metrics-dev_*.deb ./libydb-cpp-otel-tracing-dev_*.deb
./libydb-cpp-otel-metrics-dev_*.deb ./libydb-cpp-otel-tracing-dev_*.deb \
./ydb-odbc_*.deb

odbcinst -q -d -n YDB
```

After installation, use the SDK in your CMake project:
Expand Down
15 changes: 15 additions & 0 deletions cmake/PackSDK.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ set(CPACK_RESOURCE_FILE_LICENSE "${YDB_SDK_SOURCE_DIR}/LICENSE")

set(CPACK_DEB_COMPONENT_INSTALL ON)
set(CPACK_COMPONENTS_ALL libydb-cpp libydb-cpp-iam libydb-cpp-otel-metrics libydb-cpp-otel-tracing)
if (YDB_SDK_ODBC)
list(APPEND CPACK_COMPONENTS_ALL ydb-odbc)
endif()

set(CPACK_DEBIAN_LIBYDB_CPP_PACKAGE_NAME "libydb-cpp-dev")
set(CPACK_DEBIAN_LIBYDB_CPP_PACKAGE_DEPENDS
Expand All @@ -34,6 +37,18 @@ set(CPACK_DEBIAN_LIBYDB_CPP_OTEL_TRACING_PACKAGE_NAME "libydb-cpp-otel-tracing-d
set(CPACK_DEBIAN_LIBYDB_CPP_OTEL_TRACING_PACKAGE_DEPENDS
"libydb-cpp-dev (= ${YDB_SDK_VERSION}), libydb-cpp-otel-metrics-dev (= ${YDB_SDK_VERSION})")

if (YDB_SDK_ODBC)
set("CPACK_DEBIAN_YDB-ODBC_PACKAGE_NAME" "ydb-odbc")
set("CPACK_DEBIAN_YDB-ODBC_PACKAGE_DEPENDS" "odbcinst")
set("CPACK_DEBIAN_YDB-ODBC_PACKAGE_SHLIBDEPS" ON)
set("CPACK_DEBIAN_YDB-ODBC_PACKAGE_CONTROL_EXTRA"
"${YDB_ODBC_DEBIAN_CONTROL_EXTRA}")
set("CPACK_DEBIAN_YDB-ODBC_PACKAGE_CONTROL_STRICT_PERMISSION" ON)
set("CPACK_DEBIAN_YDB-ODBC_PACKAGE_SECTION" "database")
set("CPACK_DEBIAN_YDB-ODBC_DESCRIPTION"
"YDB ODBC driver\n Shared ODBC driver and unixODBC registration for YDB.")
endif()

foreach(component IN ITEMS libydb-cpp libydb-cpp-iam libydb-cpp-otel-metrics libydb-cpp-otel-tracing)
string(TOUPPER "${component}" component_upper)
string(REPLACE "-" "_" component_var "${component_upper}")
Expand Down
58 changes: 49 additions & 9 deletions odbc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,25 @@ set_target_properties(ydb-odbc PROPERTIES

include(GNUInstallDirs)

set(YDB_ODBC_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}" CACHE STRING
"Directory where the YDB ODBC shared library is installed")
set(YDB_ODBC_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}/ydb-odbc" CACHE STRING
"Directory where the YDB ODBC driver registration template is installed")

if (IS_ABSOLUTE "${YDB_ODBC_INSTALL_LIBDIR}")
set(YDB_ODBC_DRIVER_INSTALL_DIR "${YDB_ODBC_INSTALL_LIBDIR}")
else()
set(YDB_ODBC_DRIVER_INSTALL_DIR
"${CMAKE_INSTALL_PREFIX}/${YDB_ODBC_INSTALL_LIBDIR}")
endif()

if (IS_ABSOLUTE "${YDB_ODBC_INSTALL_DATADIR}")
set(YDB_ODBC_DRIVER_TEMPLATE_DIR "${YDB_ODBC_INSTALL_DATADIR}")
else()
set(YDB_ODBC_DRIVER_TEMPLATE_DIR
"${CMAKE_INSTALL_PREFIX}/${YDB_ODBC_INSTALL_DATADIR}")
endif()

file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/odbcinst.ini"
CONTENT "[YDB]
Expand All @@ -54,24 +73,45 @@ Setup=$<TARGET_FILE:ydb-odbc>
)

set(YDB_ODBC_DRIVER_PATH
"${CMAKE_INSTALL_FULL_LIBDIR}/libydb-odbc${CMAKE_SHARED_LIBRARY_SUFFIX}")
"${YDB_ODBC_DRIVER_INSTALL_DIR}/libydb-odbc${CMAKE_SHARED_LIBRARY_SUFFIX}")
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/odbcinst.ini.in"
"${CMAKE_CURRENT_BINARY_DIR}/ydb-odbc-odbcinst.ini"
@ONLY
)

set(YDB_ODBC_DRIVER_TEMPLATE_PATH
"${YDB_ODBC_DRIVER_TEMPLATE_DIR}/odbcinst.ini")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/debian")
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/packaging/postinst.in"
"${CMAKE_CURRENT_BINARY_DIR}/debian/postinst"
@ONLY
)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/packaging/prerm.in"
"${CMAKE_CURRENT_BINARY_DIR}/debian/prerm"
@ONLY
)
set(YDB_ODBC_DEBIAN_CONTROL_EXTRA
"${CMAKE_CURRENT_BINARY_DIR}/debian/postinst;${CMAKE_CURRENT_BINARY_DIR}/debian/prerm"
CACHE INTERNAL "Debian control scripts for the ydb-odbc package")

install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ydb-odbc-odbcinst.ini"
DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}/odbcinst.d"
RENAME ydb-odbc.ini
DESTINATION "${YDB_ODBC_INSTALL_DATADIR}"
RENAME odbcinst.ini
COMPONENT ydb-odbc
)

install(TARGETS ydb-odbc
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION "${YDB_ODBC_INSTALL_LIBDIR}"
COMPONENT ydb-odbc
)

install(DIRECTORY include/
DESTINATION include/ydb-odbc
)
if (YDB_SDK_EXAMPLES)
add_subdirectory(examples)
endif()

add_subdirectory(examples)
add_subdirectory(tests)
if (YDB_SDK_TESTS)
add_subdirectory(tests)
endif()
13 changes: 9 additions & 4 deletions odbc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,22 @@ The shared library is produced as `build/odbc/libydb-odbc.so`.

```bash
cmake --install build --prefix /usr/local
sudo odbcinst -i -d -f /usr/local/share/ydb-odbc/odbcinst.ini
```

Installs `libydb-odbc` and registers the driver in
`${prefix}/etc/odbcinst.d/ydb-odbc.ini`.
`odbc.ini` is not installed — create your own DSN (see below).
This installs `libydb-odbc` and its unixODBC registration template. The
`ydb-odbc` Debian package runs `odbcinst` automatically during installation
and unregisters the driver when the package is removed. `odbc.ini` is not
installed or modified — create your own DSN (see below).

## Configuration

For `SQLConnect("YDB", ...)`, `isql -v YDB`, or `Driver=YDB`.

**`odbcinst.ini`** — driver registration (generated on build/install). Section `[YDB]` is the driver name used as `Driver=YDB` in connection strings and DSNs. `Driver` and `Setup` are the full path to `libydb-odbc.so`. Use `/etc/odbcinst.ini`, a file in `/etc/odbcinst.d/`, or set `ODBCSYSINI` to the directory that contains `odbcinst.ini`.
**`odbcinst.ini`** — driver registration template (generated on build/install).
Section `[YDB]` is the driver name used as `Driver=YDB` in connection strings
and DSNs. `Driver` and `Setup` are the full path to `libydb-odbc.so`. Register
the template with `odbcinst -i -d -f`; the Debian package does this for you.

```ini
[YDB]
Expand Down
10 changes: 10 additions & 0 deletions odbc/packaging/postinst.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/sh
set -e

case "${1:-}" in
configure|abort-upgrade|abort-remove|abort-deconfigure)
odbcinst -i -d -f "@YDB_ODBC_DRIVER_TEMPLATE_PATH@"
;;
esac

exit 0
13 changes: 13 additions & 0 deletions odbc/packaging/prerm.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh
set -e

case "${1:-}" in
remove|upgrade|deconfigure)
if odbcinst -q -d -n YDB 2>/dev/null \
| grep -Fx "Driver=@YDB_ODBC_DRIVER_PATH@" >/dev/null; then
odbcinst -u -d -n YDB
fi
;;
esac

exit 0
20 changes: 20 additions & 0 deletions odbc/src/odbc_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,18 @@ SQLRETURN SQL_API SQLExecDirect(SQLHSTMT statementHandle,
});
}

SQLRETURN SQL_API SQLExecDirectW(SQLHSTMT statementHandle,
SQLWCHAR* statementText,
SQLINTEGER textLength) {
return NYdb::NOdbc::HandleOdbcExceptions<NYdb::NOdbc::TStatement>(statementHandle, [&](auto* stmt) {
auto ret = stmt->Prepare(NYdb::NOdbc::GetString(statementText, textLength));
if (ret != SQL_SUCCESS) {
return ret;
}
return stmt->Execute();
});
}

SQLRETURN SQL_API SQLPrepare(SQLHSTMT statementHandle,
SQLCHAR* statementText,
SQLINTEGER textLength) {
Expand All @@ -202,6 +214,14 @@ SQLRETURN SQL_API SQLPrepare(SQLHSTMT statementHandle,
});
}

SQLRETURN SQL_API SQLPrepareW(SQLHSTMT statementHandle,
SQLWCHAR* statementText,
SQLINTEGER textLength) {
return NYdb::NOdbc::HandleOdbcExceptions<NYdb::NOdbc::TStatement>(statementHandle, [&](auto* stmt) {
return stmt->Prepare(NYdb::NOdbc::GetString(statementText, textLength));
});
}

SQLRETURN SQL_API SQLExecute(SQLHSTMT statementHandle) {
return NYdb::NOdbc::HandleOdbcExceptions<NYdb::NOdbc::TStatement>(statementHandle, [&](auto* stmt) {
return stmt->Execute();
Expand Down
61 changes: 59 additions & 2 deletions odbc/src/utils/util.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "util.h"

#include <cctype>
#include <cstdint>

namespace NYdb::NOdbc {

Expand All @@ -17,7 +18,7 @@ void TrimInPlace(std::string& value) {

} // namespace

std::string GetString(SQLCHAR* str, SQLSMALLINT length) {
std::string GetString(SQLCHAR* str, SQLINTEGER length) {
if (!str) {
return {};
}
Expand All @@ -27,7 +28,63 @@ std::string GetString(SQLCHAR* str, SQLSMALLINT length) {
if (length <= 0) {
return {};
}
return std::string(reinterpret_cast<const char*>(str), length);
size_t size = static_cast<size_t>(length);
if (str[size - 1] == 0) {
--size;
}
return std::string(reinterpret_cast<const char*>(str), size);
}

std::string GetString(SQLWCHAR* str, SQLINTEGER length) {
if (!str) {
return {};
}

size_t size = 0;
if (length == SQL_NTS) {
while (str[size] != 0) {
++size;
}
} else if (length > 0) {
size = static_cast<size_t>(length);
if (str[size - 1] == 0) {
--size;
}
} else {
return {};
}

std::string result;
result.reserve(size);
for (size_t i = 0; i < size; ++i) {
uint32_t codePoint = str[i];
if (codePoint >= 0xd800 && codePoint <= 0xdbff) {
if (i + 1 < size && str[i + 1] >= 0xdc00 && str[i + 1] <= 0xdfff) {
codePoint = 0x10000 + ((codePoint - 0xd800) << 10) + (str[++i] - 0xdc00);
} else {
codePoint = 0xfffd;
}
} else if (codePoint >= 0xdc00 && codePoint <= 0xdfff) {
codePoint = 0xfffd;
}

if (codePoint <= 0x7f) {
result.push_back(static_cast<char>(codePoint));
} else if (codePoint <= 0x7ff) {
result.push_back(static_cast<char>(0xc0 | (codePoint >> 6)));
result.push_back(static_cast<char>(0x80 | (codePoint & 0x3f)));
} else if (codePoint <= 0xffff) {
result.push_back(static_cast<char>(0xe0 | (codePoint >> 12)));
result.push_back(static_cast<char>(0x80 | ((codePoint >> 6) & 0x3f)));
result.push_back(static_cast<char>(0x80 | (codePoint & 0x3f)));
} else {
result.push_back(static_cast<char>(0xf0 | (codePoint >> 18)));
result.push_back(static_cast<char>(0x80 | ((codePoint >> 12) & 0x3f)));
result.push_back(static_cast<char>(0x80 | ((codePoint >> 6) & 0x3f)));
result.push_back(static_cast<char>(0x80 | (codePoint & 0x3f)));
}
}
return result;
}

bool StartsWithPrefix(const char* s, size_t sLen, const char* prefix, size_t prefixLen) {
Expand Down
4 changes: 3 additions & 1 deletion odbc/src/utils/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

namespace NYdb::NOdbc {

std::string GetString(SQLCHAR* str, SQLSMALLINT length);
std::string GetString(SQLCHAR* str, SQLINTEGER length);

std::string GetString(SQLWCHAR* str, SQLINTEGER length);

bool StartsWithPrefix(const char* s, size_t sLen, const char* prefix, size_t prefixLen);

Expand Down
Loading
Loading