odbc 获取列名称 SQLColumnsW

 在dts团队工作,遇到有人报了个bug,说是snowflake在同一个server里, 如果有两个database也就是database1和database2里,同时存在着名称相同schema也相同的表格,SnowflakeDSIIDriver执行sqlcolumns会遇到重复列名的问题。给snowflake团队报了bug他们表示除非你拿出demo不然不信,于是这就是demo

#include <iostream>
#include <vector>
#include <stdio.h>
#include <sqlext.h>
#include <windows.h>  
#include <string>
#define REM_LEN 256 + 1  
#define ARRAYLEN(x)    (sizeof((x)) / sizeof(*(x)))
using namespace std;

int getColumnList(SQLWCHAR* pwszInConnStr, vector<wstring>& supportedColumns) {
    SQLHENV henv;
    SQLHDBC hdbc = SQL_NULL_HDBC;
    SQLHSTMT hstmt = 0;
    SQLRETURN retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);

    if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
        retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);

    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
    {
        return -1;
    }

    retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);

    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
    {
        return -2;
    }

    SQLSMALLINT nInConnStr = 0;
    SQLWCHAR    pwszOutConnStr[1024];
    SQLSMALLINT nOutConnStr = 0;
    nInConnStr = (SQLSMALLINT)lstrlen(pwszInConnStr);

    retcode = SQLDriverConnect(hdbc, NULL, pwszInConnStr, nInConnStr,
        pwszOutConnStr, ARRAYLEN(pwszOutConnStr), &nOutConnStr, 0);

    // Allocate statement handle  
    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) {
        return -3;
    }

    retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);

    std::wstring wsSchemaName = L"DBO";
    std::wstring wsTableName = L"TEST1";

    retcode = SQLColumnsW(hstmt, NULL, 0, (SQLWCHAR*)(wsSchemaName.c_str()), (SQLSMALLINT)wsSchemaName.length(),
        (SQLWCHAR*)(wsTableName.c_str()), (SQLSMALLINT)wsTableName.length(), NULL, 0);

    // Allocate statement handle  
    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) {
        return -4;
    }

    // Bind columns in result set to buffers  

    SQLWCHAR szColumnName[REM_LEN];
    SQLINTEGER cbColumnName;

    SQLBindCol(hstmt, 4, SQL_C_WCHAR, szColumnName, REM_LEN * 2, &cbColumnName);

    while ((retcode = SQLFetch(hstmt)) == SQL_SUCCESS) {
        wstring wsTempColName(szColumnName);
        supportedColumns.push_back(wsTempColName);
    }

    // Process data  
    // Allocate statement handle  
    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) {
        return -5;
    }

    if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
        SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
    }

    SQLDisconnect(hdbc);
}

void printVector(string cDataInConnStr, vector<wstring> vectors) {
    cout << cDataInConnStr << endl << "Column Lists:   "<<endl;
    for (int i = 0; i < vectors.size(); i++) {
        wcout << vectors[i] << "    ";
    }
    cout << endl << endl;
}

int main() {

    SQLWCHAR* cDataInConnStr = (SQLWCHAR*)L"password=1991Chani@;Driver={CData ODBC Driver for Snowflake};url=https://mi20141.central-india.azure.snowflakecomputing.com;user=chanakyaj;database=DATABASE1;";
    vector<wstring> cDataColumns;
    getColumnList(cDataInConnStr, cDataColumns);
    printVector("Driver={CData ODBC Driver for Snowflake}", cDataColumns);

    SQLWCHAR* dSIIDriverInConnStr = (SQLWCHAR*)L"server=mi20141.central-india.azure.snowflakecomputing.com;uid=chanakyaj;pwd=1991Chani@;Driver={SnowflakeDSIIDriver};database=DATABASE1;";
    vector<wstring> dSIIDrivercolumns;
    getColumnList(dSIIDriverInConnStr, dSIIDrivercolumns);
    printVector("Driver = {SnowflakeDSIIDriver}", dSIIDrivercolumns);

    return 0;
}

 

代码平平无奇,但是其中我遇到了几次问题,最主要的就是string需要加一个L, 这里面涉及到wstring,

wstring是宽char,Unicode编码,一般情况下一个字符占两个字节大小
string是窄char,AscII编码,一个字符占一个字节大小

我的代码一开始错写了第二种情况,其实编译也是有warning的, 这边建议下次直接error好吗!

Warning    C6276    Cast between semantically different string types:  char * to wchar_t *.  Use of invalid string can lead to undefined behavior.   


int main() {
    std::wstring wsSchemaName = L"DBO";
    wcout << endl << "(SQLWCHAR*)(L'DBO') result is:" << (SQLWCHAR*)(L"DBO");
    wcout << endl << "(SQLWCHAR*)('DBO') result is:" << (SQLWCHAR*)("DBO");

    cout << endl << "cout (SQLWCHAR*)(L'DBO') result is:" << (SQLWCHAR*)(L"DBO");
    cout << endl << "cout (SQLWCHAR*)('DBO') result is:" << (SQLWCHAR*)("DBO") << endl;

    return 0;
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值