I fink now is all right: 

I follow your instructions and no more call to strlen are maked. 
And utf8 chars are ignored returning the correct char index when non blob, 
and if in text have any '\0' (only in blob fields i believe), 
this code will work too. 


Porwerfull test cases: 
-- with text 
SELECT DISTINCT 'strpos(' || quote(str) || ', ' 
|| quote(substr) || ', ' 
|| CAST(ti.i * ts.s AS TEXT) || ')' as expr 
, strpos(str, substr, ti.i * ts.s) as result 
FROM (SELECT 'áéíóúáéíóúáéíóúáéíóú' as str, 'áéíóú' as substr) 
JOIN (SELECT 0 as i UNION ALL 
SELECT 1 as i UNION ALL 
SELECT 2 as i UNION ALL 
SELECT 3 as i UNION ALL 
SELECT 4 as i UNION ALL 
SELECT 5 as i) as ti 
JOIN (SELECT 1 as s UNION ALL 
SELECT -1 as s) as ts 
ORDER BY ti.i * ts.s ; 

-- with blob 
SELECT DISTINCT 'strpos(' || quote(str) || ', ' 
|| quote(substr) || ', ' 
|| CAST(ti.i * ts.s AS TEXT) || ')' as expr 
, strpos(str, substr, ti.i * ts.s) as result 
FROM (SELECT X'0001020001020001020001020001' as str, X'000102' as substr) 
JOIN (SELECT 0 as i UNION ALL 
SELECT 1 as i UNION ALL 
SELECT 2 as i UNION ALL 
SELECT 3 as i UNION ALL 
SELECT 4 as i UNION ALL 
SELECT 5 as i) as ti 
JOIN (SELECT 1 as s UNION ALL 
SELECT -1 as s) as ts 
ORDER BY ti.i * ts.s ; 

-- with integer 
SELECT DISTINCT 'strpos(' || quote(str) || ', ' 
|| quote(substr) || ', ' 
|| CAST(ti.i * ts.s AS TEXT) || ')' as expr 
, strpos(str, substr, ti.i * ts.s) as result 
FROM (SELECT 102102102102 as str, 102 as substr) 
JOIN (SELECT 0 as i UNION ALL 
SELECT 1 as i UNION ALL 
SELECT 2 as i UNION ALL 
SELECT 3 as i UNION ALL 
SELECT 4 as i UNION ALL 
SELECT 5 as i) as ti 
JOIN (SELECT 1 as s UNION ALL 
SELECT -1 as s) as ts 
ORDER BY ti.i * ts.s ; 

/******************************************************************/ 
Index: func.c 
=================================================================== 
--- func.c (revision 264) 
+++ func.c (working copy) 
@@ -117,6 +117,77 @@ 
} 

/* 
+** Implementation of the strpos() function 
+*/ 
+static void strposFunc( 
+ sqlite3_context *context, 
+ int argc, 
+ sqlite3_value **argv 
+){ 
+ const char *z; 
+ const char *z1; 
+ const char *z2; 
+ int len; 
+ int len1; 
+ int instnum; 
+ int pass; 
+ 
+ assert( argc==2 || argc==3 ); 
+ if( sqlite3_value_type(argv[1]) == SQLITE_NULL 
+ || (argc==3 && sqlite3_value_type(argv[2]) != SQLITE_INTEGER) 
+ ){ 
+ return; 
+ } 
+ 
+ z = (char*)sqlite3_value_blob(argv[0]); 
+ if (z == NULL) return; 
+ 
+ z1 = (char*)sqlite3_value_blob(argv[1]); 
+ if (z1 == NULL) return; 
+ 
+ if (argc>=3) { 
+ instnum = sqlite3_value_int64(argv[2]); 
+ if (instnum == 0) return; 
+ } else instnum = 1; 
+ 
+ len = sqlite3_value_bytes(argv[0]); 
+ len1 = sqlite3_value_bytes(argv[1]); 
+ if (instnum < 0) { 
+ pass = -1; 
+ z2 = z + len - len1; 
+ } else { 
+ pass = 1; 
+ z2 = z; 
+ } 
+ 
+ while ((z2 >= z) && ((z2 + len1) <= (z + len))) { 
+ if (memcmp(z2, z1, len1) == 0) { 
+ instnum -= pass; 
+ if (instnum == 0) break; 
+ } 
+ z2 += pass; 
+ } 
+ 
+ 
+ if (instnum == 0) { 
+ int pos = 0; 
+ if (sqlite3_value_type(argv[0]) != SQLITE_BLOB) { 
+ // remove the utf-8 chars until here 
+ while (z <= z2) { 
+ SQLITE_SKIP_UTF8((u_char*)z); 
+ ++pos; 
+ } 
+ } else { 
+ pos = (int)(z2 - z) + 1; 
+ } 
+ sqlite3_result_int64(context, pos); 
+ return; 
+ } else { 
+ sqlite3_result_int64(context, 0); 
+ } 
+} 
+ 
+/* 
** Implementation of the abs() function. 
** 
** IMP: R-23979-26855 The abs(X) function returns the absolute value of 
@@ -1527,6 +1598,8 @@ 
AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ), 
FUNCTION(typeof, 1, 0, 0, typeofFunc ), 
FUNCTION(length, 1, 0, 0, lengthFunc ), 
+ FUNCTION(strpos, 2, 0, 0, strposFunc ), 
+ FUNCTION(strpos, 3, 0, 0, strposFunc ), 
FUNCTION(substr, 2, 0, 0, substrFunc ), 
FUNCTION(substr, 3, 0, 0, substrFunc ), 
FUNCTION(abs, 1, 0, 0, absFunc ), 

/******************************************************************/ 

-- 

Atenciosamente, 

Israel Lins Albuquerque 
Desenvolvimento 
Polibrás Brasil Software Ltda. 


_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to