Bug #19566 | Cannot update or delete using SQLSetPos | ||
---|---|---|---|
Submitted: | 5 May 2006 17:10 | Modified: | 17 May 2007 20:19 |
Reporter: | Pascal Viandier | Email Updates: | |
Status: | Duplicate | Impact on me: | |
Category: | Connector / ODBC | Severity: | S1 (Critical) |
Version: | 3.51.15 | OS: | Any (Debian Linux X86) |
Assigned to: | Assigned Account | CPU Architecture: | Any |
Tags: | SQLSetPos |
[5 May 2006 17:10]
Pascal Viandier
[15 May 2006 9:28]
Tonci Grgin
Hi Pascal. Thanks for your prblem report. Can you please provide me with datadump and sample application (and/or) ODBC trace log? One question, why don't you have primary key defined, ie. why doesn't this line "UNIQUE KEY `tstidx1` (`chp1`)," look like "PRIMARY KEY (`chp1`),"?
[16 May 2006 13:04]
Pascal Viandier
Please find attached the MyODBC trace showing the problem. Interesting enough, I tried the same test using two Sparc Solaris boxes and the test produce the error "copy error" in myodbc.log. I think I found the problem and I made a patch in cursor.c in the function check_if_pk_exist() to ensure the same column name does not occur more than once in the index descriptor. It works. If you are interested I can send it. However I have not fully solved the "TODO: fix this loop..." but at least the update and delete work with SQLSetPos(). To answer your last question, the database was migrated from Informix, and the original has no primary key on any table. That's why there is no primary key in the test table since I tried to have an example as close as possible as the production database (689 tables!).
[16 May 2006 13:30]
Tonci Grgin
Pascal, feel free to do so.
[16 May 2006 13:54]
Pascal Viandier
Hi Tonci, Please find the patch in attachment. It includes a new function already_added() and a replacement for check_if_pk_exists() in "diff -u" format suitable for "patch -P0".
[17 May 2006 10:43]
Tonci Grgin
Pascal, I will have to ask you to provide test case on this one. Your log shows proper index determination but wrong repositioning. At the same time, SQLFetchScroll can use 3 ways to reposition correctly ("SQLFetchScroll fetches the specified rowset of data from the result set and returns data for all bound columns. Rowsets can be specified at an absolute or relative position or by bookmark.").
[19 May 2006 14:13]
Tonci Grgin
Pascal, this seems to escalate into real trouble as I digg through it... Test case would be nice.
[19 May 2006 16:03]
Pascal Viandier
Hi Tonci, I don't have enough time right now to give you a testcase for this bug, however I attach the source of a small C program that reproduces the problem. When running it, you will see the message "0 rows affected" because of the faulty WHERE clause. Hope this will help. Thanks
[19 May 2006 16:05]
Pascal Viandier
C source program to reproduce the bug
Attachment: mytest2.c (text/plain), 4.29 KiB.
[19 May 2006 16:08]
Pascal Viandier
One precision: The header file mytest3.h included in the program is the one provided with the MyODBC sources in the test subdirectory. Thanks Pascal
[22 May 2006 12:26]
Tonci Grgin
Hi Pascal. I was able to verify this bug with code provided on - MySQL server 5.0.22bk on Suse linux - WinXP SP2
[22 May 2006 12:27]
Tonci Grgin
ODBC log file
Attachment: 19566myodbclog.zip (application/zip, text), 7.81 KiB.
[22 May 2006 12:27]
Tonci Grgin
VS2005 sources
Attachment: Source19566.zip (application/zip, text), 5.52 KiB.
[30 Aug 2006 13:01]
Pascal Viandier
Hi, Is there any chance to see this bug solved before I retire? Pascal
[8 Mar 2007 1:43]
Jim Winstead
This should be fixed in the upcoming 3.51.14 release with the changes to properly generate the WHERE clause for positioned updates.
[15 May 2007 10:45]
Tonci Grgin
Jim, alas same thing happens with 3.51.15GA on WinXP Pro SP2 with MySQL server 5.0.38BK: Connecting to 'myodbc1'... row 1: AAA,100,MySQL1 row 2: BBB,200,MySQL2 row 3: CCC,300,MySQL3 rows affected:0 <<< Due to malformed WHERE as described. See below. -- test-end -- Modifications amde to test case: SQLCHAR connOut[255], Val[255], Rez[8]; /* buffer for connection output */ SQLSMALLINT szConnOut; /* num bytes returned in connOut */ and //rc = SQLDriverConnect(hdbc, // NULL, // (SQLCHAR *) the_dsn, SQL_NTS, // NULL, 0, NULL, // SQL_DRIVER_COMPLETE); //TEST 2 rc = SQLDriverConnect(hdbc, NULL, (SQLCHAR *)"DRIVER={MySQL ODBC 3.51 Driver};SERVER=localhost;PORT=3306;UID=root;PWD=;Database=test;OPTION=512", _countof("DRIVER={MySQL ODBC 3.51 Driver};SERVER=localhost;PORT=3306;UID=root;PWD=;Database=test;OPTION=512"), connOut, 255, &szConnOut, SQL_DRIVER_NOPROMPT); 070515 12:38:42 5 Connect root@localhost on test 5 Query SET SQL_AUTO_IS_NULL=0 070515 12:38:43 5 Query drop table tstidx 5 Query create table tstidx(chp1 char(3) default null, chp2 int default null, chp3 char(10) default null) 5 Query create unique index tstidx1 on tstidx (chp1) 5 Query create unique index tstidx2 on tstidx (chp3, chp1) 5 Query create index tstidx3 on tstidx (chp2) 5 Query insert into tstidx values('AAA', 100,'MySQL1') 5 Query insert into tstidx values('BBB', 200,'MySQL2') 5 Query insert into tstidx values('CCC', 300,'MySQL3') 5 Query select * from tstidx 070515 12:38:44 5 Query select * from tstidx where chp1='BBB' 5 Query show keys from `tstidx` 5 Query SELECT `chp1` FROM `tstidx` 5 Query UPDATE `tstidx` SET `chp1`='BBB',`chp2`=1000,`chp3`='MySQL2 ' WHERE `chp1`='BBB' AND `chp2`=200 AND `chp3`='MySQL2' AND `chp1`='AAA' LIMIT 1 5 Query select * from tstidx 070515 12:38:50 5 Query DROP DATABASE IF EXISTS client_odbc_test 5 Quit
[15 May 2007 10:47]
Tonci Grgin
Logs
Attachment: 19566-logs.zip (application/x-zip-compressed, text), 6.29 KiB.
[15 May 2007 22:37]
Jim Winstead
Here is the test case (currently flagged TODO) added to the repo for this. This is related to Bug #28255. (But with the fix for that bug, the test case changes from generating an incorrect query to refusing to do the update, which it should be able to do.) DECLARE_TEST(t_bug19566) { SQLLEN nlen; ok_sql(hstmt, "DROP TABLE IF EXISTS t_bug19566"); ok_sql(hstmt, "CREATE TABLE t_bug19566 (a INT, b INT, PRIMARY KEY (a,b), UNIQUE (b))"); ok_sql(hstmt, "INSERT INTO t_bug19566 VALUES (1,3),(1,4)"); ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); ok_stmt(hstmt, SQLSetCursorName(hstmt, (SQLCHAR *)"bug", SQL_NTS)); ok_sql(hstmt, "SELECT a FROM t_bug19566 WHERE b > 3"); ok_stmt(hstmt, SQLFetch(hstmt)); is_num(my_fetch_int(hstmt, 1), 1); ok_stmt(hstmt, SQLSetPos(hstmt, 1, SQL_POSITION, SQL_LOCK_NO_CHANGE)); ok_stmt(hstmt, SQLSetPos(hstmt, 1, SQL_DELETE, SQL_LOCK_NO_CHANGE)); ok_stmt(hstmt, SQLRowCount(hstmt, &nlen)); is_num(nlen, 1); ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_UNBIND)); ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); ok_sql(hstmt, "SELECT * FROM t_bug19566"); ok_stmt(hstmt, SQLFetch(hstmt)); is_num(my_fetch_int(hstmt, 1), 1); is_num(my_fetch_int(hstmt, 2), 3); ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); ok_sql(hstmt, "DROP TABLE IF EXISTS t_bug19566"); return OK; }
[17 May 2007 19:38]
Jim Winstead
I have an initial patch for this (that chooses the first unique/primary key for which we have all of the component elements), but developing a good set of tests is going to require the fix for Bug #28255 to be pushed first.
[17 May 2007 20:19]
Jim Winstead
This is a duplicate of Bug #10563. The fix will be handled there.