Bug #3499 SQL_COLUMN_IGNORE not checked in SQLBulkOperations
Submitted: 18 Apr 2004 21:40 Modified: 21 Oct 2005 20:04
Reporter: Steven Harding Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / ODBC Severity:S3 (Non-critical)
Version:3.51 OS:Windows (Windows)
Assigned to: CPU Architecture:Any

[18 Apr 2004 21:40] Steven Harding
Description:
    There is a problem in the MyODBC driver - it does not support the 
use of SQL_COLUMN_IGNORE in the indicator variable for a field when using SQLBulkOperations. It is being interpreted as a large negative number, and therefore is causing memory allocation errors when I attempt to add rows to a table using SQLBulkOperations and bound fields.

    The most common usage for SQL_COLUMN_IGNORE is to have a field that is 
bound (using SQLBindCol) for READING, but which you don't want used for 
WRITING (eg. an AUTO_INCREMENTING INTEGER or something similar). My own 
software uses this feature quite often. 

    Having examined the source, I have found that there is simply NO code present to deal with SQL_COLUMN_IGNORE when inserting using SQLBulkOperations. I have provided a tentative fix, but I believe this can cause problems with unbound columns.

How to repeat:
   This is most problematic when using SQLBulkOperations to add a field to a table that uses an AUTO_INCREMENT (IDENTITY) field. You bind all of the fields, set the indicator variable for the unique number to 'SQL_COLUMN_IGNORE' and then attempt to add. An error will result, as there is a massive memory allocation problem trying to allocate huge (negative) amounts of memory.

Suggested fix:
 The following changes make MyODBC function correctly when using 
SQL_COLUMN_IGNORE in SQLBulkOperations insert statements.

    All line numbers are based on the production version.

	FILE: Cursor.c
	LOCATION: Line 1033 (just after validating that there is a bound indicator 
variable in batch_insert)
	CODE: Marked with '#'
	
#	if (*bind->pcbValue == SQL_COLUMN_IGNORE) continue;

	FILE: Cursor.c
	LOCATION: Line 1218 (just inside the FOR loop that iterates through the 
fields in my_SQLSetPos, in the SQL_ADD case)
	CODE: Marked with '#'

#	PARAM_BIND parm;				
#       	BIND        *bind = stmt->bind+ncol;
#
#       	parm.buffer = (gptr)bind->rgbValue+count*bind->cbValueMax;
#
#       	if (parm.buffer)
#       	{
#         	if (bind->pcbValue)
#          	{
#			  if (*bind->pcbValue == SQL_COLUMN_IGNORE)
#			  {
#				  ncol++;
#				  continue;
#			  };
#		  };
#	};

   Effect of code changes:

	These changes alter the INSERT INTO statements generated by the 
SQLBulkOperations call so that they do not include the field name or field 
value for any bound field who has an Indicator variable equal to 
SQL_COLUMN_IGNORE.

	While it is tempting to simply just treat SQL_COLUMN_IGNORE as 
SQL_NULL_DATA, this is an incorrect implementation as it will not allow 
default column values to appear. This seems the most effective method of 
getting ignored columns to work correctly. If possible, I would like this 
to become part of the standard code, as I plan to try to eventually offer 
an optional MySQL and MyODBC license with my product - but this is not 
possible if I have to use an unofficial version of the ODBC driver.

    	I hope people have no trouble with this code change.

	Thanks,

	Steven Harding
	Push-A-Button Software
[12 Apr 2005 1:45] Peter Harvey
This was addressed in CSC-3985 and did not make into 3.51.11. It will be in next build (3.51.12).
[21 Oct 2005 20:04] Peter Harvey
see mysql-connector-odbc-3.51.12 for fix
[26 Apr 2010 10:42] Tonci Grgin
See Bug#52196