Thread overview
ODBC SQLBindParameter for string array
Jan 25, 2014
Andre
Jan 27, 2014
Regan Heath
Jan 28, 2014
Andre
January 25, 2014
Hi,

I have some issues with the ODBC SQLBindParameter. I already
achieved to add an array of integers but the scenario of writting
a string array is not working.
While doing the INSERT statement 3 rows are added to the
database. The first row has the correct value "A". The second row
has not value instead of "B". And the third row has a strange
value and the character 'P' instead of "C".

Do you have some idea?

Kind regards
André

// CREATE TABLE demo(name VARCHAR(1))
// INSERT INTO demo (name) VALUES (?)

string[] stringArr = ["A","B","C"];

SQLSetStmtAttr(hStmt, SQL_ATTR_PARAMSET_SIZE,
   cast(SQLPOINTER) stringArr.length, 0);
SQLSetStmtAttr(hStmt, SQL_ATTR_PARAM_BIND_TYPE,  cast(SQLPOINTER)
   SQL_PARAM_BIND_BY_COLUMN, 0);
SQLINTEGER[] lengIndArr = new SQLINTEGER[](table.rowCount);

// Get max length, in this example always: 1
int maxLength = 0;
foreach(str;stringArr){
   if(str.length > maxLength){
     maxLength = str.length;
   }
}

// SQLCHAR is defined as ubyte
SQLCHAR[][] charArr = new SQLCHAR[][](stringArr.length, maxLength
+ 1);
// +1 for \0 character

foreach(i, str;stringArr){
   charArr[i] =   cast(SQLCHAR[]) (str~"\0");
   lengIndArr[i] = SQL_NTS; // Null terminated string
}

SQLBindParameter( hStmt, cast(SQLUSMALLINT) 1, cast(SQLSMALLINT)
   SQL_PARAM_INPUT, cast(SQLSMALLINT)SQL_C_CHAR,
cast(SQLSMALLINT)SQL_VARCHAR,
   maxLength, 0, charArr[0].ptr , maxLength + 1, lengIndArr.ptr);
January 27, 2014
On Sat, 25 Jan 2014 11:05:11 -0000, Andre <andre@s-e-a-p.de> wrote:
> // CREATE TABLE demo(name VARCHAR(1))
> // INSERT INTO demo (name) VALUES (?)
>
> string[] stringArr = ["A","B","C"];
>
> SQLSetStmtAttr(hStmt, SQL_ATTR_PARAMSET_SIZE,
>     cast(SQLPOINTER) stringArr.length, 0);
> SQLSetStmtAttr(hStmt, SQL_ATTR_PARAM_BIND_TYPE,  cast(SQLPOINTER)
>     SQL_PARAM_BIND_BY_COLUMN, 0);
> SQLINTEGER[] lengIndArr = new SQLINTEGER[](table.rowCount);
>
> // Get max length, in this example always: 1
> int maxLength = 0;
> foreach(str;stringArr){
>     if(str.length > maxLength){
>       maxLength = str.length;
>     }
> }

Try this:

// SQLCHAR is defined as ubyte
SQLCHAR*[] charArr = new SQLCHAR*[](stringArr.length);

foreach(i, str;stringArr){
    charArr[i] =   cast(SQLCHAR*) toStringz(str); // import std.string
    lengIndArr[i] = SQL_NTS; // Null terminated string
}

The SQL API is expecting an array of (C) char* pointers, not an array of D's ubyte[] (which is actually twice the size).

> SQLBindParameter(
>   hStmt,  cast(SQLUSMALLINT) 1,  cast(SQLSMALLINT) SQL_PARAM_INPUT,  cast(SQLSMALLINT) SQL_C_CHAR,
>   cast(SQLSMALLINT)SQL_VARCHAR,
>   maxLength,  0,
>   charArr[0].ptr,
    maxLength + 1,   // I don't think the +1 is necessary..
>   lengIndArr.ptr);

Regan

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
January 28, 2014
On Monday, 27 January 2014 at 14:18:17 UTC, Regan Heath wrote:
> Try this:
>
> // SQLCHAR is defined as ubyte
> SQLCHAR*[] charArr = new SQLCHAR*[](stringArr.length);
>
> foreach(i, str;stringArr){
>     charArr[i] =   cast(SQLCHAR*) toStringz(str); // import std.string
>     lengIndArr[i] = SQL_NTS; // Null terminated string
> }
>
> The SQL API is expecting an array of (C) char* pointers, not an array of D's ubyte[] (which is actually twice the size).
>
>> SQLBindParameter(
>>  hStmt,  cast(SQLUSMALLINT) 1,  cast(SQLSMALLINT) SQL_PARAM_INPUT,
>>  cast(SQLSMALLINT) SQL_C_CHAR,
>>  cast(SQLSMALLINT)SQL_VARCHAR,
>>  maxLength,  0,
>>  charArr[0].ptr,
>     maxLength + 1,   // I don't think the +1 is necessary..
>>  lengIndArr.ptr);
>
> Regan

Thanks a lot for your help!

Kind regards
André