0

I need to get rid of fixed array size in C++/ODBC apps. Instead the hardcoded array size (ROWS =10 below) I want to pass the ROWS as the command-line argument. I know how to parse the command line. But how to adjust the following code?

    #define ROWS 10

    SQLINTEGER idata[ROWS]
    SQLCHAR cdata1[ROWS][256]
    SQLFLOAT fdata[ROWS]
    SQL_TIMESTAMP_STRUCT ts[ROWS]

    SQLSetStmtAttr(SQL_ATTR_ROW_ARRAY_SIZE, ROWS)

    SQLBindCol(1, &idata)
    SQLBindCol(2, cdata1)
    SQLBindCol(3, fdata)
    SQLBindCol(4, &ts)
    SQLExecDirect("query producing a result-set")

Update: I cannot modify the signature of SQLBindCol(..)

Let say I will create std::vector instead of SQLFLOAT fdata[ROWS] but how to pass it into SQLBindCol() which does not expect std::vector?

2
  • 4
    You cannot have variable length arrays in c++.The length of the array must be a compile time constant.You might want to consider using std::vector or std::array instead of the c-style arrays. Commented Feb 10, 2012 at 6:28
  • 2
    C++ doesn't provide variable-length arrays, but they certainly don't have to be compile-time constant. That's what new[] is for. e.g. SQLINTEGER * idata = new SQLINTEGER[rows] (and don't forget to delete[] later). The multidimensional array cdata1 is a bigger problem, because that can't be allocated dynamically. The best you can do is an array-of-arrays or a single new SQLCHAR[rows*256], one of which might work depending on how SQLBindCol works here. I don't know enough about ODBC to help more than that. Commented Feb 10, 2012 at 6:48

3 Answers 3

1

Using std::vector on fdata:

size_t rowCount = /* ... */;
std::vector<SQLFLOAT> fdata(rowCount);
// ...
SQLSetStmtAttr(SQL_ATTR_ROW_ARRAY_SIZE, rowCount);
// ...
SQLBindCol(3, &fdata[0]);
// ...

For cdata1, std::vector<SQLCHAR> cdata1(250 * rowCount); might work.

Sign up to request clarification or add additional context in comments.

Comments

0

Use pointers.

Accept the ROWS argument from command line as you said. Allocate memory of desired size (ROWS argument that you get) using dynamic memory allocation by using malloc/new to all the variables you have declared like idata, cdata1 etc. That's it!

Comments

0

I haven't managed to make it work with a 2d dynamic array. But here's a solution for a dynamic 2d array using a 1d array

std::set<std::string> getResults(int columnIndex, HSTMT stmt) {
    std::set<std::string> results;
    RETCODE rc = 0;
    int rows = 250;
    int colsize = 500 + 1; //Need to increment colunm size by 1 because SQLBindCol add the terminator character "\0"

    SQLLEN *indicator1 = new SQLLEN[rows];
    char *buff = new char[rows*colsize];
    SQLSetStmtAttr(stmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)rows, 0);

    SQLUINTEGER     NumRowsFetched;
    SQLSetStmtAttr(stmt, SQL_ATTR_ROWS_FETCHED_PTR, &NumRowsFetched, 0);

    SQLBindCol(stmt, columnIndex, SQL_C_CHAR, buff, colsize, indicator1);
    while (rc = SQLFetch(stmt) == SQL_SUCCESS) {
        for (int i = 0; (SQLUINTEGER)i < NumRowsFetched; i++) {
            results.insert(&buff[i * colsize]);
        }
    }
    delete[] buff;
    return results;

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.