Description:
After performing a SQLBulkOperations to add 10 identical integer values in a table, the values in the table do not match the values stored with SQLBulkOperations; it seems that SQLBulkOperations inserts a value *and* the following length\NULL indicator.
The code performing the SQLBulkOperations call is as follows:
unsigned char pBuffer[2048];
SQLPOINTER cbUnitSize=(SQLPOINTER)(4 + 4); // value + length\NULL indicator
SQLSetStmtAttr(m_hstmt, SQL_ATTR_ROW_BIND_TYPE, cbUnitSize, 0);
SQLBindCol(m_hstmt, 1, (SQLSMALLINT)SQL_C_SLONG, pBuffer, 4, (SQLLEN *)(pBuffer + 4));
[...]
int myValue = 1;
int cbValue = sizeof(int);
memmove(pBuffer, &myValue, 4);
memmove(pBuffer + 4, &cbValue, 4); // length\NULL indicator
pBuffer += 8;
// Repeat 10 times, storing 1,4,1,4,1,4,1,4,1,4,....
[...]
SQLPOINTER cbRecords = (SQLPOINTER)10;
SQLSetStmtAttr(m_hstmt, SQL_ATTR_ROW_ARRAY_SIZE, cbRecords, 0);
DWORD dwBindOffset = 0;
SQLSetStmtAttr(m_hstmt, SQL_ATTR_ROW_BIND_OFFSET_PTR, &dwBindOffset, 0);
SQLBulkOperations(m_hstmt, SQL_ADD);
The table shows the following data:
mysql> select * from tblevents2;
+---------+
| MyField |
+---------+
| 1 |
| 4 |
| 1 |
| 4 |
| 1 |
| 4 |
| 1 |
| 4 |
| 1 |
| 4 |
+---------+
Here's the ODBC trace file:
logparser "SELE ae8-e98 ENTER SQLAllocHandle
SQLSMALLINT 1 <SQL_HANDLE_ENV>
SQLHANDLE 00000000
SQLHANDLE * 00AF92C4
logparser "SELE ae8-e98 EXIT SQLAllocHandle with return code 0 (SQL_SUCCESS)
SQLSMALLINT 1 <SQL_HANDLE_ENV>
SQLHANDLE 00000000
SQLHANDLE * 0x00AF92C4 ( 0x00841788)
logparser "SELE ae8-e98 ENTER SQLSetEnvAttr
SQLHENV 00841788
SQLINTEGER 200 <SQL_ATTR_ODBC_VERSION>
SQLPOINTER 0x00000003
SQLINTEGER 0
logparser "SELE ae8-e98 EXIT SQLSetEnvAttr with return code 0 (SQL_SUCCESS)
SQLHENV 00841788
SQLINTEGER 200 <SQL_ATTR_ODBC_VERSION>
SQLPOINTER 0x00000003 (BADMEM)
SQLINTEGER 0
logparser "SELE ae8-e98 ENTER SQLAllocHandle
SQLSMALLINT 2 <SQL_HANDLE_DBC>
SQLHANDLE 00841788
SQLHANDLE * 00AF92C8
logparser "SELE ae8-e98 EXIT SQLAllocHandle with return code 0 (SQL_SUCCESS)
SQLSMALLINT 2 <SQL_HANDLE_DBC>
SQLHANDLE 00841788
SQLHANDLE * 0x00AF92C8 ( 0x00841830)
logparser "SELE ae8-e98 ENTER SQLSetConnectAttrW
SQLHDBC 00841830
SQLINTEGER 103 <SQL_ATTR_LOGIN_TIMEOUT>
SQLPOINTER 0x0000000F
SQLINTEGER -6
logparser "SELE ae8-e98 EXIT SQLSetConnectAttrW with return code 0 (SQL_SUCCESS)
SQLHDBC 00841830
SQLINTEGER 103 <SQL_ATTR_LOGIN_TIMEOUT>
SQLPOINTER 0x0000000F (BADMEM)
SQLINTEGER -6
logparser "SELE ae8-e98 ENTER SQLSetConnectAttrW
SQLHDBC 00841830
SQLINTEGER 1204 <unknown>
SQLPOINTER [Unknown attribute 1204]
SQLINTEGER -6
logparser "SELE ae8-e98 EXIT SQLSetConnectAttrW with return code 0 (SQL_SUCCESS)
SQLHDBC 00841830
SQLINTEGER 1204 <unknown>
SQLPOINTER [Unknown attribute 1204]
SQLINTEGER -6
logparser "SELE ae8-e98 ENTER SQLDriverConnectW
HDBC 00841830
HWND 00000000
WCHAR * 0x74329A38 [ -3] "******\ 0"
SWORD -3
WCHAR * 0x74329A38
SWORD 2
SWORD * 0x00000000
UWORD 0 <SQL_DRIVER_NOPROMPT>
logparser "SELE ae8-e98 EXIT SQLDriverConnectW with return code 0 (SQL_SUCCESS)
HDBC 00841830
HWND 00000000
WCHAR * 0x74329A38 [ -3] "******\ 0"
SWORD -3
WCHAR * 0x74329A38
SWORD 2
SWORD * 0x00000000
UWORD 0 <SQL_DRIVER_NOPROMPT>
logparser "SELE ae8-e98 ENTER SQLSetConnectAttrW
SQLHDBC 00841830
SQLINTEGER 102 <SQL_ATTR_AUTOCOMMIT>
SQLPOINTER 0x00000001
SQLINTEGER -5
logparser "SELE ae8-e98 EXIT SQLSetConnectAttrW with return code 0 (SQL_SUCCESS)
SQLHDBC 00841830
SQLINTEGER 102 <SQL_ATTR_AUTOCOMMIT>
SQLPOINTER 0x00000001 (BADMEM)
SQLINTEGER -5
logparser "SELE ae8-e98 ENTER SQLAllocHandle
SQLSMALLINT 3 <SQL_HANDLE_STMT>
SQLHANDLE 00841830
SQLHANDLE * 00AF92CC
logparser "SELE ae8-e98 EXIT SQLAllocHandle with return code 0 (SQL_SUCCESS)
SQLSMALLINT 3 <SQL_HANDLE_STMT>
SQLHANDLE 00841830
SQLHANDLE * 0x00AF92CC ( 0x00841c60)
logparser "SELE ae8-e98 ENTER SQLSetStmtAttrW
SQLHSTMT 00841C60
SQLINTEGER 6 <SQL_ATTR_CURSOR_TYPE>
SQLPOINTER 0x00000002
SQLINTEGER 0
logparser "SELE ae8-e98 EXIT SQLSetStmtAttrW with return code 1 (SQL_SUCCESS_WITH_INFO)
SQLHSTMT 00841C60
SQLINTEGER 6 <SQL_ATTR_CURSOR_TYPE>
SQLPOINTER 0x00000002 (BADMEM)
SQLINTEGER 0
DIAG [01S02] Option value changed to default static cursor (502)
logparser "SELE ae8-e98 ENTER SQLSetStmtAttrW
SQLHSTMT 00841C60
SQLINTEGER 7 <SQL_ATTR_CONCURRENCY>
SQLPOINTER 0x00000002
SQLINTEGER 0
logparser "SELE ae8-e98 EXIT SQLSetStmtAttrW with return code 0 (SQL_SUCCESS)
SQLHSTMT 00841C60
SQLINTEGER 7 <SQL_ATTR_CONCURRENCY>
SQLPOINTER 0x00000002 (BADMEM)
SQLINTEGER 0
logparser "SELE ae8-e98 ENTER SQLPrepareW
HSTMT 00841C60
WCHAR * 0x0006E804 [ 24] "SELECT * FROM tblEvents2"
SDWORD 24
logparser "SELE ae8-e98 EXIT SQLPrepareW with return code 0 (SQL_SUCCESS)
HSTMT 00841C60
WCHAR * 0x0006E804 [ 24] "SELECT * FROM tblEvents2"
SDWORD 24
logparser "SELE ae8-e98 ENTER SQLExecute
HSTMT 00841C60
logparser "SELE ae8-e98 EXIT SQLExecute with return code -1 (SQL_ERROR)
HSTMT 00841C60
DIAG [42S01] Table 'eventlog.tblevents2' doesn't exist (1146)
logparser "SELE ae8-e98 ENTER SQLAllocHandle
SQLSMALLINT 3 <SQL_HANDLE_STMT>
SQLHANDLE 00841830
SQLHANDLE * 0006DF0C
logparser "SELE ae8-e98 EXIT SQLAllocHandle with return code 0 (SQL_SUCCESS)
SQLSMALLINT 3 <SQL_HANDLE_STMT>
SQLHANDLE 00841830
SQLHANDLE * 0x0006DF0C ( 0x00842538)
logparser "SELE ae8-e98 ENTER SQLExecDirectW
HSTMT 00842538
WCHAR * 0x00B0E130 [ -3] "CREATE TABLE tblEvents2 ( MyField int)\ 0"
SDWORD -3
logparser "SELE ae8-e98 EXIT SQLExecDirectW with return code 0 (SQL_SUCCESS)
HSTMT 00842538
WCHAR * 0x00B0E130 [ -3] "CREATE TABLE tblEvents2 ( MyField int)\ 0"
SDWORD -3
logparser "SELE ae8-e98 ENTER SQLFreeHandle
SQLSMALLINT 3 <SQL_HANDLE_STMT>
SQLHANDLE 00842538
logparser "SELE ae8-e98 EXIT SQLFreeHandle with return code 0 (SQL_SUCCESS)
SQLSMALLINT 3 <SQL_HANDLE_STMT>
SQLHANDLE 00842538
logparser "SELE ae8-e98 ENTER SQLPrepareW
HSTMT 00841C60
WCHAR * 0x0006E804 [ 24] "SELECT * FROM tblEvents2"
SDWORD 24
logparser "SELE ae8-e98 EXIT SQLPrepareW with return code 0 (SQL_SUCCESS)
HSTMT 00841C60
WCHAR * 0x0006E804 [ 24] "SELECT * FROM tblEvents2"
SDWORD 24
logparser "SELE ae8-e98 ENTER SQLExecute
HSTMT 00841C60
logparser "SELE ae8-e98 EXIT SQLExecute with return code 0 (SQL_SUCCESS)
HSTMT 00841C60
logparser "SELE ae8-e98 ENTER SQLNumResultCols
HSTMT 00841C60
SWORD * 0x0006DF9E
logparser "SELE ae8-e98 EXIT SQLNumResultCols with return code 0 (SQL_SUCCESS)
HSTMT 00841C60
SWORD * 0x0006DF9E (1)
logparser "SELE ae8-e98 ENTER SQLColAttributeW
SQLHSTMT 00841C60
SQLSMALLINT 1
SQLSMALLINT 1011 <SQL_DESC_NAME>
SQLPOINTER 0x00000000
SQLSMALLINT 0
SQLSMALLINT * 0x0006DF68
SQLPOINTER [Unknown attribute 1011]
logparser "SELE ae8-e98 EXIT SQLColAttributeW with return code 1 (SQL_SUCCESS_WITH_INFO)
SQLHSTMT 00841C60
SQLSMALLINT 1
SQLSMALLINT 1011 <SQL_DESC_NAME>
SQLPOINTER 0x00000000
SQLSMALLINT 0
SQLSMALLINT * 0x0006DF68 (7)
SQLPOINTER [Unknown attribute 1011]
logparser "SELE ae8-e98 ENTER SQLColAttributeW
SQLHSTMT 00841C60
SQLSMALLINT 1
SQLSMALLINT 1011 <SQL_DESC_NAME>
SQLPOINTER 0x00AF9540
SQLSMALLINT 9
SQLSMALLINT * 0x0006DF68
SQLPOINTER [Unknown attribute 1011]
logparser "SELE ae8-e98 EXIT SQLColAttributeW with return code 1 (SQL_SUCCESS_WITH_INFO)
SQLHSTMT 00841C60
SQLSMALLINT 1
SQLSMALLINT 1011 <SQL_DESC_NAME>
SQLPOINTER 0x00AF9540
SQLSMALLINT 9
SQLSMALLINT * 0x0006DF68 (14)
SQLPOINTER [Unknown attribute 1011]
logparser "SELE ae8-e98 ENTER SQLColAttributeW
SQLHSTMT 00841C60
SQLSMALLINT 1
SQLSMALLINT 1002 <SQL_DESC_TYPE>
SQLPOINTER 0x00000000
SQLSMALLINT 0
SQLSMALLINT * 0x00000000
SQLPOINTER [Unknown attribute 1002]
logparser "SELE ae8-e98 EXIT SQLColAttributeW with return code 0 (SQL_SUCCESS)
SQLHSTMT 00841C60
SQLSMALLINT 1
SQLSMALLINT 1002 <SQL_DESC_TYPE>
SQLPOINTER 0x00000000
SQLSMALLINT 0
SQLSMALLINT * 0x00000000
SQLPOINTER [Unknown attribute 1002]
logparser "SELE ae8-e98 ENTER SQLColAttributeW
SQLHSTMT 00841C60
SQLSMALLINT 1
SQLSMALLINT 1008 <SQL_DESC_NULLABLE>
SQLPOINTER 0x00000000
SQLSMALLINT 0
SQLSMALLINT * 0x00000000
SQLPOINTER [Unknown attribute 1008]
logparser "SELE ae8-e98 EXIT SQLColAttributeW with return code 0 (SQL_SUCCESS)
SQLHSTMT 00841C60
SQLSMALLINT 1
SQLSMALLINT 1008 <SQL_DESC_NULLABLE>
SQLPOINTER 0x00000000
SQLSMALLINT 0
SQLSMALLINT * 0x00000000
SQLPOINTER [Unknown attribute 1008]
logparser "SELE ae8-e98 ENTER SQLColAttributeW
SQLHSTMT 00841C60
SQLSMALLINT 1
SQLSMALLINT 11 <SQL_DESC_AUTO_UNIQUE_VALUE>
SQLPOINTER 0x00000000
SQLSMALLINT 0
SQLSMALLINT * 0x00000000
SQLPOINTER 0x0006DFA0
logparser "SELE ae8-e98 EXIT SQLColAttributeW with return code 0 (SQL_SUCCESS)
SQLHSTMT 00841C60
SQLSMALLINT 1
SQLSMALLINT 11 <SQL_DESC_AUTO_UNIQUE_VALUE>
SQLPOINTER 0x00000000
SQLSMALLINT 0
SQLSMALLINT * 0x00000000
SQLPOINTER 0x0006DFA0 (0)
logparser "SELE ae8-e98 ENTER SQLColAttributeW
SQLHSTMT 00841C60
SQLSMALLINT 1
SQLSMALLINT 1013 <SQL_DESC_OCTET_LENGTH>
SQLPOINTER 0x00000000
SQLSMALLINT 0
SQLSMALLINT * 0x00000000
SQLPOINTER [Unknown attribute 1013]
logparser "SELE ae8-e98 EXIT SQLColAttributeW with return code 0 (SQL_SUCCESS)
SQLHSTMT 00841C60
SQLSMALLINT 1
SQLSMALLINT 1013 <SQL_DESC_OCTET_LENGTH>
SQLPOINTER 0x00000000
SQLSMALLINT 0
SQLSMALLINT * 0x00000000
SQLPOINTER [Unknown attribute 1013]
logparser "SELE ae8-e98 ENTER SQLSetStmtAttrW
SQLHSTMT 00841C60
SQLINTEGER 5 <SQL_ATTR_ROW_BIND_TYPE>
SQLPOINTER 0x00000008
SQLINTEGER 0
logparser "SELE ae8-e98 EXIT SQLSetStmtAttrW with return code 0 (SQL_SUCCESS)
SQLHSTMT 00841C60
SQLINTEGER 5 <SQL_ATTR_ROW_BIND_TYPE>
SQLPOINTER 0x00000008 (BADMEM)
SQLINTEGER 0
logparser "SELE ae8-e98 ENTER SQLBindCol
HSTMT 00841C60
UWORD 1
SWORD -16 <SQL_C_SLONG>
PTR 0x00F90000
SQLLEN 4
SQLLEN * 0x00F90004
logparser "SELE ae8-e98 EXIT SQLBindCol with return code 0 (SQL_SUCCESS)
HSTMT 00841C60
UWORD 1
SWORD -16 <SQL_C_SLONG>
PTR 0x00F90000
SQLLEN 4
SQLLEN * 0x00F90004 (0)
logparser "SELE ae8-e98 ENTER SQLSetStmtAttrW
SQLHSTMT 00841C60
SQLINTEGER 27 <SQL_ATTR_ROW_ARRAY_SIZE>
SQLPOINTER 0x0000000A
SQLINTEGER 0
logparser "SELE ae8-e98 EXIT SQLSetStmtAttrW with return code 0 (SQL_SUCCESS)
SQLHSTMT 00841C60
SQLINTEGER 27 <SQL_ATTR_ROW_ARRAY_SIZE>
SQLPOINTER 0x0000000A (BADMEM)
SQLINTEGER 0
logparser "SELE ae8-e98 ENTER SQLSetStmtAttrW
SQLHSTMT 00841C60
SQLINTEGER 23 <SQL_ATTR_ROW_BIND_OFFSET_PTR>
SQLPOINTER 0006F840
SQLINTEGER 0
logparser "SELE ae8-e98 EXIT SQLSetStmtAttrW with return code 0 (SQL_SUCCESS)
SQLHSTMT 00841C60
SQLINTEGER 23 <SQL_ATTR_ROW_BIND_OFFSET_PTR>
SQLPOINTER 0006F840
SQLINTEGER 0
logparser "SELE ae8-e98 ENTER SQLBulkOperations
SQLHSTMT 00841C60
SQLSMALLINT 4
logparser "SELE ae8-e98 EXIT SQLBulkOperations with return code 0 (SQL_SUCCESS)
SQLHSTMT 00841C60
SQLSMALLINT 4
logparser "SELE ae8-e98 ENTER SQLFreeHandle
SQLSMALLINT 3 <SQL_HANDLE_STMT>
SQLHANDLE 00841C60
logparser "SELE ae8-e98 EXIT SQLFreeHandle with return code 0 (SQL_SUCCESS)
SQLSMALLINT 3 <SQL_HANDLE_STMT>
SQLHANDLE 00841C60
logparser "SELE ae8-e98 ENTER SQLDisconnect
HDBC 00841830
logparser "SELE ae8-e98 EXIT SQLDisconnect with return code 0 (SQL_SUCCESS)
HDBC 00841830
logparser "SELE ae8-e98 ENTER SQLFreeHandle
SQLSMALLINT 2 <SQL_HANDLE_DBC>
SQLHANDLE 00841830
logparser "SELE ae8-e98 EXIT SQLFreeHandle with return code 0 (SQL_SUCCESS)
SQLSMALLINT 2 <SQL_HANDLE_DBC>
SQLHANDLE 00841830
logparser "SELE ae8-e98 ENTER SQLFreeHandle
SQLSMALLINT 1 <SQL_HANDLE_ENV>
SQLHANDLE 00841788
logparser "SELE ae8-e98 EXIT SQLFreeHandle with return code 0 (SQL_SUCCESS)
SQLSMALLINT 1 <SQL_HANDLE_ENV>
SQLHANDLE 00841788
Here's the table definition:
mysql> desc tblevents2;
+---------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+-------+
| MyField | int(11) | YES | | NULL | |
+---------+---------+------+-----+---------+-------+
How to repeat:
Windows XP SP2;
MySQL 4.1;
MyODBC 3.51.11;
Microsoft Log Parser 2.2 (from http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8...);
- Create a MySQL database called "eventlogs";
- Get the Log Parser 2.2 executable and run the following command:
logparser "SELECT top 10 1 AS MyField from system to tblEvents" -o:SQL -server:localhost -driver:"MySQL ODBC 3.51 Driver" -database:eventlog -username:root -password:<your password here> -createtable:ON -clearTable:ON
(the command creates the target table as defined above and inserts 10 integer fields with value = 1)
- Check the newly-created "tblEvents" table:
Expected:
+---------+
| MyField |
+---------+
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
+---------+
Actual:
+---------+
| MyField |
+---------+
| 1 |
| 4 |
| 1 |
| 4 |
| 1 |
| 4 |
| 1 |
| 4 |
| 1 |
| 4 |
+---------+