Skip to content

Commit 248844c

Browse files
committed
step
1 parent 33fd643 commit 248844c

18 files changed

+835
-187
lines changed

odbc/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
add_library(ydb-odbc SHARED
2+
src/utils/result.cpp
3+
src/utils/types.cpp
4+
src/utils/util.cpp
25
src/utils/convert.cpp
36
src/odbc_driver.cpp
47
src/connection.cpp
@@ -9,13 +12,15 @@ add_library(ydb-odbc SHARED
912
target_include_directories(ydb-odbc
1013
PRIVATE
1114
${CMAKE_CURRENT_SOURCE_DIR}/include
15+
${CMAKE_CURRENT_SOURCE_DIR}/src
1216
${ODBC_INCLUDE_DIRS}
1317
)
1418

1519
target_link_libraries(ydb-odbc
1620
PRIVATE
1721
YDB-CPP-SDK::Query
1822
YDB-CPP-SDK::Table
23+
YDB-CPP-SDK::Scheme
1924
YDB-CPP-SDK::Driver
2025
ODBC::ODBC
2126
)

odbc/examples/CMakeLists.txt

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

odbc/examples/scheme/CMakeLists.txt

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

odbc/examples/scheme/main.cpp

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

odbc/src/connection.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ SQLRETURN TConnection::DriverConnect(const std::string& connectionString) {
4444
.SetDatabase(Database_));
4545

4646
YdbClient_ = std::make_unique<NYdb::NQuery::TQueryClient>(*YdbDriver_);
47+
YdbSchemeClient_ = std::make_unique<NYdb::NScheme::TSchemeClient>(*YdbDriver_);
48+
YdbTableClient_ = std::make_unique<NYdb::NTable::TTableClient>(*YdbDriver_);
4749

4850
return SQL_SUCCESS;
4951
}
@@ -71,6 +73,8 @@ SQLRETURN TConnection::Connect(const std::string& serverName,
7173
.SetDatabase(Database_));
7274

7375
YdbClient_ = std::make_unique<NYdb::NQuery::TQueryClient>(*YdbDriver_);
76+
YdbSchemeClient_ = std::make_unique<NYdb::NScheme::TSchemeClient>(*YdbDriver_);
77+
YdbTableClient_ = std::make_unique<NYdb::NTable::TTableClient>(*YdbDriver_);
7478

7579
return SQL_SUCCESS;
7680
}

odbc/src/connection.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#include <ydb-cpp-sdk/client/driver/driver.h>
66
#include <ydb-cpp-sdk/client/query/client.h>
7+
#include <ydb-cpp-sdk/client/scheme/scheme.h>
8+
#include <ydb-cpp-sdk/client/table/table.h>
79

810
#include <sql.h>
911
#include <sqlext.h>
@@ -21,6 +23,8 @@ class TConnection {
2123
private:
2224
std::unique_ptr<TDriver> YdbDriver_;
2325
std::unique_ptr<NQuery::TQueryClient> YdbClient_;
26+
std::unique_ptr<NTable::TTableClient> YdbTableClient_;
27+
std::unique_ptr<NScheme::TSchemeClient> YdbSchemeClient_;
2428
std::optional<NQuery::TTransaction> Tx_;
2529

2630
TErrorList Errors_;
@@ -45,6 +49,8 @@ class TConnection {
4549
void RemoveStatement(TStatement* stmt);
4650

4751
NYdb::NQuery::TQueryClient* GetClient() { return YdbClient_.get(); }
52+
NYdb::NTable::TTableClient* GetTableClient() { return YdbTableClient_.get(); }
53+
NScheme::TSchemeClient* GetSchemeClient() { return YdbSchemeClient_.get(); }
4854

4955
void AddError(const std::string& sqlState, SQLINTEGER nativeError, const std::string& message);
5056
void ClearErrors();

odbc/src/odbc_driver.cpp

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,11 @@
22
#include "connection.h"
33
#include "statement.h"
44

5+
#include "utils/util.h"
6+
57
#include <sql.h>
68
#include <sqlext.h>
79

8-
namespace {
9-
std::string GetString(SQLCHAR* str, SQLSMALLINT length) {
10-
if (length == SQL_NTS) {
11-
return std::string(reinterpret_cast<const char*>(str));
12-
}
13-
return std::string(reinterpret_cast<const char*>(str), length);
14-
}
15-
}
16-
1710
extern "C" {
1811

1912
SQLRETURN SQL_API SQLAllocHandle(SQLSMALLINT handleType,
@@ -122,7 +115,7 @@ SQLRETURN SQL_API SQLDriverConnect(SQLHDBC connectionHandle,
122115
return SQL_INVALID_HANDLE;
123116
}
124117

125-
return conn->DriverConnect(GetString(inConnectionString, stringLength1));
118+
return conn->DriverConnect(NYdb::NOdbc::GetString(inConnectionString, stringLength1));
126119
}
127120

128121
SQLRETURN SQL_API SQLConnect(SQLHDBC connectionHandle,
@@ -134,9 +127,9 @@ SQLRETURN SQL_API SQLConnect(SQLHDBC connectionHandle,
134127
return SQL_INVALID_HANDLE;
135128
}
136129

137-
return conn->Connect(GetString(serverName, nameLength1),
138-
GetString(userName, nameLength2),
139-
GetString(authentication, nameLength3));
130+
return conn->Connect(NYdb::NOdbc::GetString(serverName, nameLength1),
131+
NYdb::NOdbc::GetString(userName, nameLength2),
132+
NYdb::NOdbc::GetString(authentication, nameLength3));
140133
}
141134

142135
SQLRETURN SQL_API SQLDisconnect(SQLHDBC connectionHandle) {
@@ -156,7 +149,7 @@ SQLRETURN SQL_API SQLExecDirect(SQLHSTMT statementHandle,
156149
return SQL_INVALID_HANDLE;
157150
}
158151

159-
return stmt->ExecDirect(GetString(statementText, textLength));
152+
return stmt->ExecDirect(NYdb::NOdbc::GetString(statementText, textLength));
160153
}
161154

162155
SQLRETURN SQL_API SQLFetch(SQLHSTMT statementHandle) {
@@ -308,4 +301,36 @@ SQLRETURN SQL_API SQLSetConnectAttr(SQLHDBC connectionHandle, SQLINTEGER attribu
308301
return SQL_ERROR;
309302
}
310303

304+
SQLRETURN SQL_API SQLColumns(SQLHSTMT statementHandle,
305+
SQLCHAR* catalogName, SQLSMALLINT nameLength1,
306+
SQLCHAR* schemaName, SQLSMALLINT nameLength2,
307+
SQLCHAR* tableName, SQLSMALLINT nameLength3,
308+
SQLCHAR* columnName, SQLSMALLINT nameLength4) {
309+
auto stmt = static_cast<NYdb::NOdbc::TStatement*>(statementHandle);
310+
if (!stmt) {
311+
return SQL_INVALID_HANDLE;
312+
}
313+
return stmt->Columns(
314+
NYdb::NOdbc::GetString(catalogName, nameLength1),
315+
NYdb::NOdbc::GetString(schemaName, nameLength2),
316+
NYdb::NOdbc::GetString(tableName, nameLength3),
317+
NYdb::NOdbc::GetString(columnName, nameLength4));
318+
}
319+
320+
SQLRETURN SQL_API SQLTables(SQLHSTMT statementHandle,
321+
SQLCHAR* catalogName, SQLSMALLINT nameLength1,
322+
SQLCHAR* schemaName, SQLSMALLINT nameLength2,
323+
SQLCHAR* tableName, SQLSMALLINT nameLength3,
324+
SQLCHAR* tableType, SQLSMALLINT nameLength4) {
325+
auto stmt = static_cast<NYdb::NOdbc::TStatement*>(statementHandle);
326+
if (!stmt) {
327+
return SQL_INVALID_HANDLE;
328+
}
329+
return stmt->Tables(
330+
NYdb::NOdbc::GetString(catalogName, nameLength1),
331+
NYdb::NOdbc::GetString(schemaName, nameLength2),
332+
NYdb::NOdbc::GetString(tableName, nameLength3),
333+
NYdb::NOdbc::GetString(tableType, nameLength4));
334+
}
335+
311336
}

0 commit comments

Comments
 (0)