Hi everybody, I found a strange behaviour of SQLite (3.6.19) when it relies on a custom collation during a SELECT execution. So let me explain the matter from the beginning: I've got the following simple table: CREATE TABLE Genre ( id INTEGER NOT NULL UNIQUE, name VARCHAR(20) NOT NULL UNIQUE COLLATE MYCOLLATE, image_id INT NOT NULL, PRIMARY KEY (id), CONSTRAINT fk_Genre FOREIGN KEY (image_id) REFERENCES Image (id) ON DELETE SET NULL ON UPDATE CASCADE);
-- Indeces CREATE INDEX Genre_name_idx ON Genre(name); and I fill it as follows: INSERT INTO Genre VALUES(0,'',0); INSERT INTO Genre VALUES(1,'Blues',0); INSERT INTO Genre VALUES(2,'Classic Rock',0); INSERT INTO Genre VALUES(3,'Country',0); INSERT INTO Genre VALUES(4,'Dance',0); INSERT INTO Genre VALUES(5,'Disco',0); INSERT INTO Genre VALUES(6,'Funk',0); INSERT INTO Genre VALUES(7,'Grunge',0); INSERT INTO Genre VALUES(8,'Hip-Hop',0); INSERT INTO Genre VALUES(9,'Jazz',0); ... Then, when I try to execute: SELECT id FROM Genre WHERE name = 'Jazz' it doesn't yield any results. On the other hand, when I execute the following statement: INSERT INTO Genre(name,image_id) VALUES('Jazz',0) SQLite correctly returns this errors: SQLITE_CONSTRAINT[19]: constraint failed SQLITE_CONSTRAINT[19]: column name is not unique So my first thought was: my collation method has some bugs! So I used the NOCASE bult-in collate: name VARCHAR(20) NOT NULL UNIQUE COLLATE NOCASE and it works fine. The next step was to try again MYCOLLATE and compare all results of MYCOLLATE method with the NOCASE ones. To do that I write the following piece of code: int MyClass::xCompare (void* v, int iLen1, const void* str1, int iLen2, const void* str2) { //MYCOLLATE std::wstring s1; std::wstring s2; CStringConverter::FromUTF8toUCS2 ((const BYTE *) str1,iLen1, s1); CStringConverter::FromUTF8toUCS2 ((const BYTE *) str2,iLen2, s2); int iRes = CCollationStringComparer::Compare(s1.length(), s1.c_str(), s2.length(), s2.c_str()); //NOCASE int r = sqlite3StrNICmp( (const char *)str1, (const char *)str2, (iLen1<iLen2)?iLen1:iLen2); UNUSED_PARAMETER(v); if( 0==r ){ r = iLen1-iLen2; } bool bNegative = (iRes < 0) && (r < 0); bool bZero = (iRes == 0) && (r == 0); bool bPositive = (iRes > 0) && (r > 0); assert(bNegative || bZero || bPositive); return iRes; } and I registered it: sqlite3_create_collation(mpDB,”MYCOLLATE", SQLITE_UTF8, NULL, MyClass::xCompare); As you can see the assert condition ensures me that the two methods yield the same results. That's the strange behaviour: no assert is ever triggered even if the SELECT statement keeps yielding no result; but if I change return iRes; with return r; it works fine! I point out that CCollationStringComparer::Compare always returns 1,0,-1 whereas sqlite3StrNICmp returns different values (but always with the same sign!). Any ideas about what's happening? Could it be a SQLite bug? Cheers _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users