Skip to content

Commit 21882de

Browse files
committed
ODBC MVP
1 parent bbb3e8a commit 21882de

20 files changed

+1099
-594
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ add_subdirectory(c_api)
6565
#_ydb_sdk_validate_public_headers()
6666

6767
if (YDB_SDK_ODBC)
68-
#add_subdirectory(odbc)
68+
add_subdirectory(odbc)
6969
endif()
7070

7171
if (YDB_SDK_EXAMPLES)

c_api/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
add_library(ydb-c-api STATIC
1+
_ydb_sdk_add_library(ydb-c-api SHARED)
2+
3+
target_sources(ydb-c-api PRIVATE
24
src/driver.cpp
35
src/query.cpp
46
src/result.cpp

cmake/common.cmake

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ function(generate_enum_serilization Tgt Input)
115115
endfunction()
116116

117117
function(add_global_library_for TgtName MainName)
118-
add_library(${TgtName} STATIC ${ARGN})
118+
_ydb_sdk_add_library(${TgtName} STATIC ${ARGN})
119119
if(APPLE)
120120
target_link_options(${MainName} INTERFACE "SHELL:-Wl,-force_load,$<TARGET_FILE:$<INSTALL_INTERFACE:YDB-CPP-SDK::>${TgtName}>")
121121
else()
@@ -182,7 +182,7 @@ endfunction()
182182

183183
function(_ydb_sdk_add_library Tgt)
184184
cmake_parse_arguments(ARG
185-
"INTERFACE;OBJECT" "" ""
185+
"INTERFACE;OBJECT;SHARED" "" ""
186186
${ARGN}
187187
)
188188

@@ -195,6 +195,9 @@ function(_ydb_sdk_add_library Tgt)
195195
if (ARG_OBJECT)
196196
set(libraryMode "OBJECT")
197197
endif()
198+
if (ARG_SHARED)
199+
set(libraryMode "SHARED")
200+
endif()
198201
add_library(${Tgt} ${libraryMode})
199202
target_include_directories(${Tgt} ${includeMode}
200203
$<BUILD_INTERFACE:${YDB_SDK_SOURCE_DIR}>
@@ -204,6 +207,7 @@ function(_ydb_sdk_add_library Tgt)
204207
target_compile_definitions(${Tgt} ${includeMode}
205208
YDB_SDK_USE_STD_STRING
206209
)
210+
set_property(TARGET ${Tgt} PROPERTY POSITION_INDEPENDENT_CODE ON)
207211
endfunction()
208212

209213
function(_ydb_sdk_validate_public_headers)

cmake/external_libs.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ find_package(jwt-cpp REQUIRED)
1515
find_package(GTest REQUIRED)
1616
find_package(double-conversion REQUIRED)
1717

18+
if (YDB_SDK_ODBC)
19+
find_package(ODBC REQUIRED)
20+
endif()
21+
1822
# RapidJSON
1923
if (YDB_SDK_USE_RAPID_JSON)
2024
find_package(RapidJSON REQUIRED)

odbc/CMakeLists.txt

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,31 @@
1-
cmake_minimum_required(VERSION 3.14)
2-
project(ydb-odbc VERSION 0.1.0 LANGUAGES C CXX)
3-
4-
set(CMAKE_CXX_STANDARD 20)
5-
set(CMAKE_CXX_STANDARD_REQUIRED ON)
6-
set(CMAKE_CXX_EXTENSIONS OFF)
7-
8-
# Находим зависимости
9-
find_package(ODBC REQUIRED)
10-
111
# Добавляем исходники
122
add_library(ydb-odbc SHARED
13-
src/driver.c
14-
src/connection.c
15-
src/statement.c
16-
src/descriptor.c
17-
src/client/driver.cpp
18-
src/client/query.cpp
3+
src/odbc_driver.cpp
4+
src/connection.cpp
5+
src/statement.cpp
6+
src/environment.cpp
197
)
208

219
# Добавляем заголовочные файлы
2210
target_include_directories(ydb-odbc
23-
PUBLIC
11+
PRIVATE
2412
${CMAKE_CURRENT_SOURCE_DIR}/include
2513
${ODBC_INCLUDE_DIRS}
26-
/usr/include
27-
/usr/local/include
2814
)
2915

3016
# Линкуем с YDB SDK и ODBC
3117
target_link_libraries(ydb-odbc
32-
PUBLIC
18+
PRIVATE
3319
ydb-cpp-sdk::Query
3420
ydb-cpp-sdk::Table
3521
ydb-cpp-sdk::Driver
3622
ODBC::ODBC
3723
)
3824

25+
set_target_properties(ydb-odbc PROPERTIES
26+
POSITION_INDEPENDENT_CODE ON
27+
)
28+
3929
# Устанавливаем драйвер
4030
install(TARGETS ydb-odbc
4131
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
@@ -46,6 +36,8 @@ install(DIRECTORY include/
4636
DESTINATION include/ydb-odbc
4737
)
4838

39+
add_subdirectory(examples)
40+
4941
# Добавляем тесты
5042
# add_subdirectory(tests)
5143

odbc/examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add_subdirectory(basic)

odbc/examples/basic/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
add_executable(odbc_basic
2+
main.cpp
3+
)
4+
5+
target_link_libraries(odbc_basic
6+
PRIVATE
7+
ODBC::ODBC
8+
)
9+
target_compile_definitions(odbc_basic
10+
PRIVATE
11+
ODBC_DRIVER_PATH="$<TARGET_FILE:ydb-odbc>"
12+
)
13+
14+
add_dependencies(odbc_basic ydb-odbc)

odbc/examples/basic/main.cpp

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#include <sql.h>
2+
#include <sqlext.h>
3+
4+
#include <iostream>
5+
#include <cstring>
6+
#include <cstdlib>
7+
#include <cstdint>
8+
9+
void PrintOdbcError(SQLSMALLINT handleType, SQLHANDLE handle) {
10+
SQLCHAR sqlState[6] = {0};
11+
SQLINTEGER nativeError = 0;
12+
SQLCHAR message[256] = {0};
13+
SQLSMALLINT textLength = 0;
14+
SQLGetDiagRec(handleType, handle, 1, sqlState, &nativeError, message, sizeof(message), &textLength);
15+
std::cerr << "ODBC error: [" << sqlState << "] " << message << std::endl;
16+
}
17+
18+
int main() {
19+
SQLHENV henv = nullptr;
20+
SQLHDBC hdbc = nullptr;
21+
SQLHSTMT hstmt = nullptr;
22+
SQLRETURN ret;
23+
24+
std::cout << "1. Allocating environment handle" << std::endl;
25+
ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
26+
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
27+
std::cerr << "Error allocating environment handle" << std::endl;
28+
return 1;
29+
}
30+
SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
31+
32+
std::cout << "2. Allocating connection handle" << std::endl;
33+
ret = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
34+
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
35+
std::cerr << "Error allocating connection handle" << std::endl;
36+
SQLFreeHandle(SQL_HANDLE_ENV, henv);
37+
return 1;
38+
}
39+
40+
std::cout << "3. Building connection string" << std::endl;
41+
std::string connStr = "Driver=" ODBC_DRIVER_PATH ";Endpoint=localhost:2136;Database=/local;";
42+
SQLCHAR outConnStr[1024] = {0};
43+
SQLSMALLINT outConnStrLen = 0;
44+
45+
std::cout << "4. Connecting with SQLDriverConnect" << std::endl;
46+
ret = SQLDriverConnect(hdbc, NULL, (SQLCHAR*)connStr.c_str(), SQL_NTS,
47+
outConnStr, sizeof(outConnStr), &outConnStrLen, SQL_DRIVER_COMPLETE);
48+
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
49+
std::cerr << "Error connecting with SQLDriverConnect" << std::endl;
50+
PrintOdbcError(SQL_HANDLE_DBC, hdbc);
51+
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
52+
SQLFreeHandle(SQL_HANDLE_ENV, henv);
53+
return 1;
54+
}
55+
56+
std::cout << "5. Allocating statement handle" << std::endl;
57+
ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
58+
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
59+
std::cerr << "Error allocating statement handle" << std::endl;
60+
SQLDisconnect(hdbc);
61+
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
62+
SQLFreeHandle(SQL_HANDLE_ENV, henv);
63+
return 1;
64+
}
65+
66+
std::cout << "6. Executing query" << std::endl;
67+
SQLCHAR query[] = R"(
68+
DECLARE $p1 AS Int64;
69+
SELECT $p1 + 1, 'test1' as String;
70+
SELECT $p1 + 2, 'test2' as String;
71+
SELECT $p1 + 3, 'test3' as String;
72+
SELECT $p1 + 4, 'test4' as String;
73+
SELECT $p1 + 5, 'test5' as String;
74+
SELECT $p1 + 6, 'test6' as String;
75+
SELECT $p1 + 7, 'test7' as String;
76+
SELECT $p1 + 8, 'test8' as String;
77+
SELECT $p1 + 9, 'test9' as String;
78+
)";
79+
80+
int64_t paramValue = 42;
81+
SQLLEN paramInd = 0;
82+
ret = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, &paramValue, 0, &paramInd);
83+
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
84+
std::cerr << "Error binding parameter" << std::endl;
85+
PrintOdbcError(SQL_HANDLE_STMT, hstmt);
86+
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
87+
SQLDisconnect(hdbc);
88+
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
89+
SQLFreeHandle(SQL_HANDLE_ENV, henv);
90+
return 1;
91+
}
92+
93+
ret = SQLExecDirect(hstmt, query, SQL_NTS);
94+
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
95+
std::cerr << "Error executing query" << std::endl;
96+
PrintOdbcError(SQL_HANDLE_STMT, hstmt);
97+
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
98+
SQLDisconnect(hdbc);
99+
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
100+
SQLFreeHandle(SQL_HANDLE_ENV, henv);
101+
return 1;
102+
}
103+
104+
std::cout << "7. Fetching result" << std::endl;
105+
106+
SQLLEN ind = 0;
107+
int value1 = 0;
108+
if (SQLBindCol(hstmt, 1, SQL_C_SLONG, &value1, 0, &ind) != SQL_SUCCESS) {
109+
std::cerr << "Error binding column 1" << std::endl;
110+
PrintOdbcError(SQL_HANDLE_STMT, hstmt);
111+
return 1;
112+
}
113+
114+
SQLCHAR value2[1024] = {0};
115+
if (SQLBindCol(hstmt, 2, SQL_C_CHAR, &value2, 1024, &ind) != SQL_SUCCESS) {
116+
std::cerr << "Error binding column 2" << std::endl;
117+
PrintOdbcError(SQL_HANDLE_STMT, hstmt);
118+
return 1;
119+
}
120+
121+
while ((ret = SQLFetch(hstmt)) == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
122+
if (ret != SQL_SUCCESS) {
123+
std::cerr << "Error fetching result" << std::endl;
124+
PrintOdbcError(SQL_HANDLE_STMT, hstmt);
125+
return 1;
126+
}
127+
128+
std::cout << "Result column 1: " << value1 << std::endl;
129+
std::cout << "Result column 2: " << value2 << std::endl;
130+
131+
std::cout << "--------------------------------" << std::endl;
132+
}
133+
134+
std::cout << "8. Cleaning up" << std::endl;
135+
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
136+
SQLDisconnect(hdbc);
137+
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
138+
SQLFreeHandle(SQL_HANDLE_ENV, henv);
139+
140+
return 0;
141+
}

odbc/include/ydb_odbc.h

Lines changed: 0 additions & 89 deletions
This file was deleted.

0 commit comments

Comments
 (0)