alexbrainman / odbc

odbc driver written in go
BSD 3-Clause "New" or "Revised" License
352 stars 140 forks source link

SQLFETCH returning error when used after SQLBindCol and SQLColumns API #142

Open iamSnehalS opened 4 years ago

iamSnehalS commented 4 years ago

Hi Alex, I am new to odbc APIs and adding SQLColumns and SQLProcedure APIs to this package "api". When running the go test using this API I am not able to fetch the rows returned by above APIs.

PFB the test code :

API: func SQLColumns(statementHandle SQLHSTMT, CatalogName SQLCHAR, NameLength1 SQLSMALLINT, SchemaName SQLCHAR, NameLength2 SQLSMALLINT, TableName SQLCHAR, NameLength3 SQLSMALLINT, ColumnName SQLCHAR, NameLength4 SQLSMALLINT) (ret SQLRETURN) { r := C.SQLColumns(C.SQLHSTMT(statementHandle), (C.SQLCHAR)(CatalogName), C.SQLSMALLINT(NameLength1), (C.SQLCHAR)(SchemaName), C.SQLSMALLINT(NameLength2), (C.SQLCHAR)(TableName), C.SQLSMALLINT(NameLength3), (C.SQLCHAR)(ColumnName), C.SQLSMALLINT(NameLength4)) return SQLRETURN(r)

}

Go Test: func TestSQLColumnsAPI(t testing.T) { db, sc, err := mssqlConnect() if err != nil { t.Fatal(err) } defer closeDB(t, db, sc, sc) var out api.SQLHANDLE d := db.Driver().(Driver).h

ret := api.SQLAllocHandle(api.SQL_HANDLE_DBC, api.SQLHANDLE(d), &out)
if IsError(ret) {
    log.Printf("error", NewError("SQLAllocHandle", out))
    // return nil, nil, NewError("SQLAllocHandle", d.h)
}
h := api.SQLHDBC(out)
drv.Stats.updateHandleCount(api.SQL_HANDLE_DBC, 1)
dsn := "pwd=password1;driver=DataDirect 8.0 SQL Server Wire Protocol;server=HOST;database=DBTest;uid=user1;"
b := api.StringToUTF16(dsn)
ret = api.SQLDriverConnect(h, 0,
    (*api.SQLWCHAR)(unsafe.Pointer(&b[0])), api.SQL_NTS,
    nil, 0, nil, api.SQL_DRIVER_NOPROMPT)
if IsError(ret) {
    log.Printf("error", NewError("SQLDriverConnect", out))
    defer releaseHandle(h)
}

ret2, err3 := **columnsCheck(h)**
if ret2 != api.SQL_SUCCESS {
    log.Printf("error :", err3)
}

}

columnsCheck() function: func columnsCheck(h api.SQLHDBC) (api.SQLRETURN, error) { var szSchema api.SQLCHAR var szCatalog api.SQLCHAR var szColumnName api.SQLCHAR var szTableName api.SQLCHAR var szTypeName api.SQLCHAR var szRemarks api.SQLCHAR var szColumnDefault api.SQLCHAR var szIsNullable api.SQLCHAR

STR_LEN := 128 + 1
REM_LEN := 254 + 1

var ColumnSize api.SQLINTEGER
var BufferLength api.SQLINTEGER
var CharOctetLength api.SQLINTEGER
var OrdinalPosition api.SQLINTEGER

var DataType api.SQLSMALLINT
var DecimalDigits api.SQLSMALLINT
var NumPrecRadix api.SQLSMALLINT
var Nullable api.SQLSMALLINT
var SQLDataType api.SQLSMALLINT
var DatetimeSubtypeCode api.SQLSMALLINT

var hstmt api.SQLHSTMT = nil

// Declare buffers for bytes available to return
var cbCatalog api.SQLLEN
var cbSchema api.SQLLEN
var cbTableName api.SQLLEN
var cbColumnName api.SQLLEN
var cbDataType api.SQLLEN
var cbTypeName api.SQLLEN
var cbColumnSize api.SQLLEN
var cbBufferLength api.SQLLEN
var cbDecimalDigits api.SQLLEN
var cbNumPrecRadix api.SQLLEN
var cbNullable api.SQLLEN
var cbRemarks api.SQLLEN
var cbColumnDefault api.SQLLEN
var cbSQLDataType api.SQLLEN
var cbDatetimeSubtypeCode api.SQLLEN
var cbCharOctetLength api.SQLLEN
var cbOrdinalPosition api.SQLLEN
var cbIsNullable api.SQLLEN

var retcode api.SQLRETURN
var out api.SQLHANDLE

retcode = api.SQLAllocHandle(api.SQL_HANDLE_STMT, api.SQLHANDLE(h), &out)
if IsError(retcode) {
    return retcode, NewError("SQLAllocHandle", hstmt)
}
hstmt = api.SQLHSTMT(out)
err := drv.Stats.updateHandleCount(api.SQL_HANDLE_STMT, 1)
if err != nil {
    return retcode, NewError("updateHandleCount", hstmt)
}
table := "emp"
tablename := api.StringToUTF16(table)
retcode = api.SQLColumns(hstmt, nil, 0, nil, 0, (*api.SQLCHAR)(unsafe.Pointer(&tablename)), api.SQL_NTS, nil, 0)

if retcode == api.SQL_SUCCESS || retcode == api.SQL_SUCCESS_WITH_INFO {
    // Bind columns in result set to buffers
    api.SQLBindCol(hstmt, 1, api.SQL_C_CHAR, (api.SQLPOINTER)(&szCatalog), api.SQLLEN(STR_LEN), &cbCatalog)
    api.SQLBindCol(hstmt, 2, api.SQL_C_CHAR, (api.SQLPOINTER)(&szSchema), api.SQLLEN(STR_LEN), &cbSchema)
    api.SQLBindCol(hstmt, 3, api.SQL_C_CHAR, (api.SQLPOINTER)(&szTableName), api.SQLLEN(STR_LEN), &cbTableName)
    api.SQLBindCol(hstmt, 4, api.SQL_C_CHAR, (api.SQLPOINTER)(&szColumnName), api.SQLLEN(STR_LEN), &cbColumnName)
    api.SQLBindCol(hstmt, 5, api.SQL_C_SSHORT, (api.SQLPOINTER)(&DataType), 0, &cbDataType)
    api.SQLBindCol(hstmt, 6, api.SQL_C_CHAR, (api.SQLPOINTER)(&szTypeName), 10, &cbTypeName)
    api.SQLBindCol(hstmt, 7, api.SQL_C_SLONG, (api.SQLPOINTER)(&ColumnSize), 0, &cbColumnSize)
    api.SQLBindCol(hstmt, 8, api.SQL_C_SLONG, (api.SQLPOINTER)(&BufferLength), 0, &cbBufferLength)
    api.SQLBindCol(hstmt, 9, api.SQL_C_SSHORT, (api.SQLPOINTER)(&DecimalDigits), 0, &cbDecimalDigits)
    api.SQLBindCol(hstmt, 10, api.SQL_C_SSHORT, (api.SQLPOINTER)(&NumPrecRadix), 0, &cbNumPrecRadix)
    api.SQLBindCol(hstmt, 11, api.SQL_C_SSHORT, (api.SQLPOINTER)(&Nullable), 0, &cbNullable)
    api.SQLBindCol(hstmt, 12, api.SQL_C_CHAR, (api.SQLPOINTER)(&szRemarks), api.SQLLEN(REM_LEN), &cbRemarks)
    api.SQLBindCol(hstmt, 13, api.SQL_C_CHAR, (api.SQLPOINTER)(&szColumnDefault), api.SQLLEN(STR_LEN), &cbColumnDefault)
    api.SQLBindCol(hstmt, 14, api.SQL_C_SSHORT, (api.SQLPOINTER)(&SQLDataType), 0, &cbSQLDataType)
    api.SQLBindCol(hstmt, 15, api.SQL_C_SSHORT, (api.SQLPOINTER)(&DatetimeSubtypeCode), 0, &cbDatetimeSubtypeCode)
    api.SQLBindCol(hstmt, 16, api.SQL_C_SLONG, (api.SQLPOINTER)(&CharOctetLength), 0, &cbCharOctetLength)
    api.SQLBindCol(hstmt, 17, api.SQL_C_SLONG, (api.SQLPOINTER)(&OrdinalPosition), 0, &cbOrdinalPosition)
    api.SQLBindCol(hstmt, 18, api.SQL_C_CHAR, (api.SQLPOINTER)(&szIsNullable), api.SQLLEN(STR_LEN), &cbIsNullable)

    for api.SQL_SUCCESS == retcode {
        retcode = api.SQLFetch(hstmt)
        /*
               if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO)
                  0;   // show_error();
               if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
                  0;   // Process fetched data
               else
                  break;
        */
    }
}
return retcode, nil

}

When i debugged , api.SQLColumns returned SQL_SUCCESS. But api.SQLFETCH is returning error code. ERROR message : mssql_test.go:175: unexpected StmtCount: should=0, is=1

Can you please check the code and guide what I am missing? Thanks alot in advance.

Thanks, Snehal

alexbrainman commented 4 years ago

I am new to odbc APIs and adding SQLColumns and SQLProcedure APIs to this package "api".

I have never used SQLColumns or SQLProcedure APIs myself.

When running the go test using this API I am not able to fetch the rows returned by above APIs. ... When i debugged , api.SQLColumns returned SQL_SUCCESS. But api.SQLFETCH is returning error code. ERROR message : mssql_test.go:175: unexpected StmtCount: should=0, is=1

It is difficult to say. You error refer to some file / line number. It is impossible to say what is on that line. If you want me to debug your code, please, share it with me somehow. Git or use zip or something. Or publish it at https://play.golang.org. But it should be self contained program that I can run to see your error message. Thank you.

Why do you want to add SQLColumns and SQLProcedure APIs? What is the problem that you are trying to solve?

Alex