天天看點

sqlite3 engine claims no such function when compiling sql statement

本文介紹了sqlite3解析和編譯SQL語句時, 宿主語言設定的定制函數找不到的issue; 主要引用相關代碼, 描述了sqlite編譯SQL語句的大緻流程.

[GENERAL DESCRIPTION:]

Process: com.sonyericsson.album

Flags: 0x8be45

Package: com.xxxxxxxxx.album

Build: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:userdebug/release-keys

java.lang.RuntimeException: An error occured while executing doInBackground()

 at android.os.AsyncTask$3.done(AsyncTask.java:299)

 at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)

 at java.util.concurrent.FutureTask.setException(FutureTask.java:124)

 at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)

 at java.util.concurrent.FutureTask.run(FutureTask.java:137)

 at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)

 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)

 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)

 at java.lang.Thread.run(Thread.java:856)

Caused by: android.database.sqlite.SQLiteException: no such function: _OBJECT_REMOVED (code 1): , while compiling: DELETE FROM files WHERE _id = 3406

 at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:184)

 at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)

 at android.content.ContentProviderProxy.delete(ContentProviderNative.java:484)

 at android.content.ContentResolver.delete(ContentResolver.java:956)

 at com.sonyericsson.album.camera.MenuExecutor.executeOperationInBackground(MenuExecutor.java:145)

 at com.sonyericsson.album.camera.MenuExecutor.access$000(MenuExecutor.java:36)

 at com.sonyericsson.album.camera.MenuExecutor$OperationExecutor.doInBackground(MenuExecutor.java:122)

 at com.sonyericsson.album.camera.MenuExecutor$OperationExecutor.doInBackground(MenuExecutor.java:109)

 at android.os.AsyncTask$2.call(AsyncTask.java:287)

 at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)

 ... 5 more

[Analysis]

For the exception string android.database.sqlite.SQLiteException: no such function: _OBJECT_REMOVED (code 1): , while compiling: DELETE FROM files WHERE _id = 3406,

the 'while compiling: %s' part is printed out by native function nativePrepareStatement().

nativePrepareStatement() @ android_database_SQLiteConnection.cpp

282static jint nativePrepareStatement(JNIEnv* env, jclass clazz, jint connectionPtr,

283        jstring sqlString) {

284    SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);

285

286    jsize sqlLength = env->GetStringLength(sqlString);

287    const jchar* sql = env->GetStringCritical(sqlString, NULL);

288    sqlite3_stmt* statement;

289    int err = sqlite3_prepare16_v2(connection->db,  *******************************

290            sql, sqlLength * sizeof(jchar), &statement, NULL);

291    env->ReleaseStringCritical(sqlString, sql);

292

293    if (err != SQLITE_OK) {

294        // Error messages like 'near ")": syntax error' are not

295        // always helpful enough, so construct an error string that

296        // includes the query itself.

297        const char *query = env->GetStringUTFChars(sqlString, NULL);

298        char *message = (char*) malloc(strlen(query) + 50);

299        if (message) {

300            strcpy(message, ", while compiling: "); // less than 50 chars ********************

301            strcat(message, query);

302        }

303        env->ReleaseStringUTFChars(sqlString, query);

304        throw_sqlite3_exception(env, connection->db, message);

305        free(message);

306        return 0;

307    }

308

309    ALOGV("Prepared statement %p on connection %p", statement, connection->db);

310    return reinterpret_cast<jint>(statement);

311}

while the "no such function" string part is printed by sqlite3 sql statement parse function.

94512SQLITE_API int sqlite3_prepare16_v2(

94513  sqlite3 *db,             

94514  const void *zSql,        

94515  int nBytes,              

94516  sqlite3_stmt **ppStmt,   

94517  const void **pzTail      

94518){

94519  int rc;

94520  rc = sqlite3Prepare16(db,zSql,nBytes,1,ppStmt,pzTail);

94521  assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); 

94522  return rc;

94523}

calls------->>

94450static int sqlite3Prepare16(

94451  sqlite3 *db,             

94452  const void *zSql,        

94453  int nBytes,              

94454  int saveSqlFlag,         

94455  sqlite3_stmt **ppStmt,   

94456  const void **pzTail      

94457){

94458 

94462  char *zSql8;

94463  const char *zTail8 = 0;

94464  int rc = SQLITE_OK;

94465

94466  assert( ppStmt );

94467  *ppStmt = 0;

94468  if( !sqlite3SafetyCheckOk(db) ){

94469    return SQLITE_MISUSE_BKPT;

94470  }

94471  sqlite3_mutex_enter(db->mutex);

94472  zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);

94473  if( zSql8 ){

94474    rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8);

94475  }

94476

94477  if( zTail8 && pzTail ){

94478   

94483    int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8));

94484    *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);

94485  }

94486  sqlite3DbFree(db, zSql8);

94487  rc = sqlite3ApiExit(db, rc);

94488  sqlite3_mutex_leave(db->mutex);

94489  return rc;

94490}

calls------>>

94348static int sqlite3LockAndPrepare(

94349  sqlite3 *db,             

94350  const char *zSql,        

94351  int nBytes,              

94352  int saveSqlFlag,         

94353  Vdbe *pOld,              

94354  sqlite3_stmt **ppStmt,   

94355  const char **pzTail      

94356){

94357  int rc;

94358  assert( ppStmt!=0 );

94359  *ppStmt = 0;

94360  if( !sqlite3SafetyCheckOk(db) ){

94361    return SQLITE_MISUSE_BKPT;

94362  }

94363  sqlite3_mutex_enter(db->mutex);

94364  sqlite3BtreeEnterAll(db);

94365  rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);

94366  if( rc==SQLITE_SCHEMA ){

94367    sqlite3_finalize(*ppStmt);

94368    rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);

94369  }

94370  sqlite3BtreeLeaveAll(db);

94371  sqlite3_mutex_leave(db->mutex);

94372  return rc;

94373}

calls------>>

94185

94188static int sqlite3Prepare(

94189  sqlite3 *db,             

94190  const char *zSql,        

94191  int nBytes,              

94192  int saveSqlFlag,         

94193  Vdbe *pReprepare,        

94194  sqlite3_stmt **ppStmt,   

94195  const char **pzTail      

94196){

94197  Parse *pParse;           

94198  char *zErrMsg = 0;       

94199  int rc = SQLITE_OK;      

94200  int i;                   

94201

94202 

94203  pParse = sqlite3StackAllocZero(db, sizeof(*pParse));

94204  if( pParse==0 ){

94205    rc = SQLITE_NOMEM;

94206    goto end_prepare;

94207  }

94208  pParse->pReprepare = pReprepare;

94209  assert( ppStmt && *ppStmt==0 );

94210  assert( !db->mallocFailed );

94211  assert( sqlite3_mutex_held(db->mutex) );

94212

94213 

94236  for(i=0; i<db->nDb; i++) {

94237    Btree *pBt = db->aDb[i].pBt;

94238    if( pBt ){

94239      assert( sqlite3BtreeHoldsMutex(pBt) );

94240      rc = sqlite3BtreeSchemaLocked(pBt);

94241      if( rc ){

94242        const char *zDb = db->aDb[i].zName;

94243        sqlite3Error(db, rc, "database schema is locked: %s", zDb);

94244        testcase( db->flags & SQLITE_ReadUncommitted );

94245        goto end_prepare;

94246      }

94247    }

94248  }

94249

94250  sqlite3VtabUnlockList(db);

94251

94252  pParse->db = db;

94253  pParse->nQueryLoop = (double)1;

94254  if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){

94255    char *zSqlCopy;

94256    int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];

94257    testcase( nBytes==mxLen );

94258    testcase( nBytes==mxLen+1 );

94259    if( nBytes>mxLen ){

94260      sqlite3Error(db, SQLITE_TOOBIG, "statement too long");

94261      rc = sqlite3ApiExit(db, SQLITE_TOOBIG);

94262      goto end_prepare;

94263    }

94264    zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);

94265    if( zSqlCopy ){

94266      sqlite3RunParser(pParse, zSqlCopy, &zErrMsg);  ******************************

94267      sqlite3DbFree(db, zSqlCopy);

94268      pParse->zTail = &zSql[pParse->zTail-zSqlCopy];

94269    }else{

94270      pParse->zTail = &zSql[nBytes];

94271    }

94272  }else{

94273    sqlite3RunParser(pParse, zSql, &zErrMsg); ********************************

94274  }

94275  assert( 1==(int)pParse->nQueryLoop );

94276

94277  if( db->mallocFailed ){

94278    pParse->rc = SQLITE_NOMEM;

94279  }

94280  if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK;

94281  if( pParse->checkSchema ){

94282    schemaIsValid(pParse);

94283  }

94284  if( db->mallocFailed ){

94285    pParse->rc = SQLITE_NOMEM;

94286  }

94287  if( pzTail ){

94288    *pzTail = pParse->zTail;

94289  }

94290  rc = pParse->rc;

94291

94292#ifndef SQLITE_OMIT_EXPLAIN

94293  if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){

94294    static const char * const azColName[] = {

94295       "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",

94296       "selectid", "order", "from", "detail"

94297    };

94298    int iFirst, mx;

94299    if( pParse->explain==2 ){

94300      sqlite3VdbeSetNumCols(pParse->pVdbe, 4);

94301      iFirst = 8;

94302      mx = 12;

94303    }else{

94304      sqlite3VdbeSetNumCols(pParse->pVdbe, 8);

94305      iFirst = 0;

94306      mx = 8;

94307    }

94308    for(i=iFirst; i<mx; i++){

94309      sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME,

94310                            azColName[i], SQLITE_STATIC);

94311    }

94312  }

94313#endif

94314

94315  assert( db->init.busy==0 || saveSqlFlag==0 );

94316  if( db->init.busy==0 ){

94317    Vdbe *pVdbe = pParse->pVdbe;

94318    sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag);

94319  }

94320  if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){

94321    sqlite3VdbeFinalize(pParse->pVdbe);

94322    assert(!(*ppStmt));

94323  }else{

94324    *ppStmt = (sqlite3_stmt*)pParse->pVdbe;

94325  }

94326

94327  if( zErrMsg ){

94328    sqlite3Error(db, rc, "%s", zErrMsg);

94329    sqlite3DbFree(db, zErrMsg);

94330  }else{

94331    sqlite3Error(db, rc, 0);

94332  }

94333

94334 

94335  while( pParse->pTriggerPrg ){

94336    TriggerPrg *pT = pParse->pTriggerPrg;

94337    pParse->pTriggerPrg = pT->pNext;

94338    sqlite3DbFree(db, pT);

94339  }

94340

94341end_prepare:

94342

94343  sqlite3StackFree(db, pParse);

94344  rc = sqlite3ApiExit(db, rc);

94345  assert( (rc&db->errMask)==rc );

94346  return rc;

94347}

sqlite3RunParser() calls sqlite3Parser() to parse the sql statement, and compile it using the following

yy_reduce, lexical analysis.

resolveOrderByTermToExprList \

resolveOrderGroupBy          |

resolveSelectStep            |

resolveAttachExpr            |

sqlite3EndTable              \

sqlite3DeleteFrom **         / sqlite3ResolveExprNames

fkScanChildren               |

sqlite3Insert                |

codeRowTrigger               |

sqlite3Update                /

The sql statement is consist of severial sub-clause, such as CRUD, ORDER BY, GROUP BY, LIKE, HAVING.

Every sub-clause is compiled by a yy_reduce entry.

These sub-clause compiling functions call sqlite3ResolveExprNames or sqlite3ResolveSelectNames.

sqlite3ResolveExprNames is one most important routine to compile sql statement.

In this issue, the DELETE is compiled by sqlite3DeleteFrom(...) which calls sqlite3ResolveExprNames.

The source of sqlite3ResolveExprNames & sqlite3ResolveSelectNames list as follows.

============================================================================================

74340SQLITE_PRIVATE int sqlite3ResolveExprNames(

74341  NameContext *pNC,      

74342  Expr *pExpr            

74343){

74344  int savedHasAgg;

74345  Walker w;

74346

74347  if( pExpr==0 ) return 0;

74348#if SQLITE_MAX_EXPR_DEPTH>0

74349  {

74350    Parse *pParse = pNC->pParse;

74351    if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){

74352      return 1;

74353    }

74354    pParse->nHeight += pExpr->nHeight;

74355  }

74356#endif

74357  savedHasAgg = pNC->hasAgg;

74358  pNC->hasAgg = 0;

74359  w.xExprCallback = resolveExprStep;  *****************

74360  w.xSelectCallback = resolveSelectStep;

74361  w.pParse = pNC->pParse;

74362  w.u.pNC = pNC;

74363  sqlite3WalkExpr(&w, pExpr);   ****************

74364#if SQLITE_MAX_EXPR_DEPTH>0

74365  pNC->pParse->nHeight -= pExpr->nHeight;

74366#endif

74367  if( pNC->nErr>0 || w.pParse->nErr>0 ){

74368    ExprSetProperty(pExpr, EP_Error);

74369  }

74370  if( pNC->hasAgg ){

74371    ExprSetProperty(pExpr, EP_Agg);

74372  }else if( savedHasAgg ){

74373    pNC->hasAgg = 1;

74374  }

74375  return ExprHasProperty(pExpr, EP_Error);

74376}

-------------------------------------------------------------------

74391SQLITE_PRIVATE void sqlite3ResolveSelectNames(

74392  Parse *pParse,        

74393  Select *p,            

74394  NameContext *pOuterNC 

74395){

74396  Walker w;

74397

74398  assert( p!=0 );

74399  w.xExprCallback = resolveExprStep; ***************

74400  w.xSelectCallback = resolveSelectStep;

74401  w.pParse = pParse;

74402  w.u.pNC = pOuterNC;

74403  sqlite3WalkSelect(&w, p);  *************************

74404}

===========================================================================================

sqlite3ResolveExprNames(...) uses sqlite3WalkExpr(...) with worker callbacks to resolve expression names.

The ExprCallback field is resolveExprStep(...).

The source of resolveExprStep(...) is following.

Notice the first line comment of the function, it is callback for sqlite3WalkExpr().

73615** This routine is callback for sqlite3WalkExpr().

73616**

73617** Resolve symbolic names into TK_COLUMN operators for the current

73618** node in the expression tree.  Return 0 to continue the search down

73619** the tree or 2 to abort the tree walk.

73620**

73621** This routine also does error checking and name resolution for

73622** function names.  The operator for aggregate functions is changed

73623** to TK_AGG_FUNCTION.

73624*/

73625static int resolveExprStep(Walker *pWalker, Expr *pExpr){

73626  NameContext *pNC;

73627  Parse *pParse;

73628

73629  pNC = pWalker->u.pNC;

73630  assert( pNC!=0 );

73631  pParse = pNC->pParse;

73632  assert( pParse==pWalker->pParse );

73633

73634  if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return WRC_Prune;

73635  ExprSetProperty(pExpr, EP_Resolved);

73636#ifndef NDEBUG

73637  if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){

73638    SrcList *pSrcList = pNC->pSrcList;

73639    int i;

73640    for(i=0; i<pNC->pSrcList->nSrc; i++){

73641      assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);

73642    }

73643  }

73644#endif

73645  switch( pExpr->op ){

73646

73647#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)

73648   

73652    case TK_ROW: {

73653      SrcList *pSrcList = pNC->pSrcList;

73654      struct SrcList_item *pItem;

73655      assert( pSrcList && pSrcList->nSrc==1 );

73656      pItem = pSrcList->a;

73657      pExpr->op = TK_COLUMN;

73658      pExpr->pTab = pItem->pTab;

73659      pExpr->iTable = pItem->iCursor;

73660      pExpr->iColumn = -1;

73661      pExpr->affinity = SQLITE_AFF_INTEGER;

73662      break;

73663    }

73664#endif

73665

73666   

73668    case TK_ID: {

73669      return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr);

73670    }

73671

73672   

73675    case TK_DOT: {

73676      const char *zColumn;

73677      const char *zTable;

73678      const char *zDb;

73679      Expr *pRight;

73680

73681     

73682      pRight = pExpr->pRight;

73683      if( pRight->op==TK_ID ){

73684        zDb = 0;

73685        zTable = pExpr->pLeft->u.zToken;

73686        zColumn = pRight->u.zToken;

73687      }else{

73688        assert( pRight->op==TK_DOT );

73689        zDb = pExpr->pLeft->u.zToken;

73690        zTable = pRight->pLeft->u.zToken;

73691        zColumn = pRight->pRight->u.zToken;

73692      }

73693      return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);

73694    }

73695

73696   

73698    case TK_CONST_FUNC:

73699    case TK_FUNCTION: {

73700      ExprList *pList = pExpr->x.pList;   

73701      int n = pList ? pList->nExpr : 0;   

73702      int no_such_func = 0;      

73703      int wrong_num_args = 0;    

73704      int is_agg = 0;            

73705      int auth;                  

73706      int nId;                   

73707      const char *zId;           

73708      FuncDef *pDef;             

73709      u8 enc = ENC(pParse->db);  

73710

73711      testcase( pExpr->op==TK_CONST_FUNC );

73712      assert( !ExprHasProperty(pExpr, EP_xIsSelect) );

73713      zId = pExpr->u.zToken;

73714      nId = sqlite3Strlen30(zId);

73715      pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);   *****************

73716      if( pDef==0 ){

73717        pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0); *****************

73718        if( pDef==0 ){

73719          no_such_func = 1;

73720        }else{

73721          wrong_num_args = 1;

73722        }

73723      }else{

73724        is_agg = pDef->xFunc==0;

73725      }

73726#ifndef SQLITE_OMIT_AUTHORIZATION

73727      if( pDef ){

73728        auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);

73729        if( auth!=SQLITE_OK ){

73730          if( auth==SQLITE_DENY ){

73731            sqlite3ErrorMsg(pParse, "not authorized to use function: %s",

73732                                    pDef->zName);

73733            pNC->nErr++;

73734          }

73735          pExpr->op = TK_NULL;

73736          return WRC_Prune;

73737        }

73738      }

73739#endif

73740      if( is_agg && !pNC->allowAgg ){

73741        sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);

73742        pNC->nErr++;

73743        is_agg = 0;

73744      }else if( no_such_func ){

73745        sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);  **************

73746        pNC->nErr++;

73747      }else if( wrong_num_args ){

73748        sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",

73749             nId, zId);

73750        pNC->nErr++;

73751      }

73752      if( is_agg ){

73753        pExpr->op = TK_AGG_FUNCTION;

73754        pNC->hasAgg = 1;

73755      }

73756      if( is_agg ) pNC->allowAgg = 0;

73757      sqlite3WalkExprList(pWalker, pList);

73758      if( is_agg ) pNC->allowAgg = 1;

73759     

73762      return WRC_Prune;

73763    }

73764#ifndef SQLITE_OMIT_SUBQUERY

73765    case TK_SELECT:

73766    case TK_EXISTS:  testcase( pExpr->op==TK_EXISTS );

73767#endif

73768    case TK_IN: {

73769      testcase( pExpr->op==TK_IN );

73770      if( ExprHasProperty(pExpr, EP_xIsSelect) ){

73771        int nRef = pNC->nRef;

73772#ifndef SQLITE_OMIT_CHECK

73773        if( pNC->isCheck ){

73774          sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");

73775        }

73776#endif

73777        sqlite3WalkSelect(pWalker, pExpr->x.pSelect);

73778        assert( pNC->nRef>=nRef );

73779        if( nRef!=pNC->nRef ){

73780          ExprSetProperty(pExpr, EP_VarSelect);

73781        }

73782      }

73783      break;

73784    }

73785#ifndef SQLITE_OMIT_CHECK

73786    case TK_VARIABLE: {

73787      if( pNC->isCheck ){

73788        sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");

73789      }

73790      break;

73791    }

73792#endif

73793  }

73794  return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;

73795}

For the opcodes of TK_CONST_FUNC and TK_FUNCTION, the sqlite3FindFunction is used to find the registerred custom function of host language.

85332

85352SQLITE_PRIVATE FuncDef *sqlite3FindFunction(

85353  sqlite3 *db,      

85354  const char *zName,

85355  int nName,        

85356  int nArg,         

85357  u8 enc,           

85358  int createFlag    

85359){

85360  FuncDef *p;        

85361  FuncDef *pBest = 0;

85362  int bestScore = 0; 

85363  int h;             

85364

85365

85366  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );

85367  h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a);

85368

85369 

85371  p = functionSearch(&db->aFunc, h, zName, nName);

85372  while( p ){

85373    int score = matchQuality(p, nArg, enc);

85374    if( score>bestScore ){

85375      pBest = p;

85376      bestScore = score;

85377    }

85378    p = p->pNext;

85379  }

85380

85381 

85393  if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){

85394    FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);

85395    bestScore = 0;

85396    p = functionSearch(pHash, h, zName, nName);

85397    while( p ){

85398      int score = matchQuality(p, nArg, enc);

85399      if( score>bestScore ){

85400        pBest = p;

85401        bestScore = score;

85402      }

85403      p = p->pNext;

85404    }

85405  }

85406

85407 

85411  if( createFlag && (bestScore<6 || pBest->nArg!=nArg) &&

85412      (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){

85413    pBest->zName = (char *)&pBest[1];

85414    pBest->nArg = (u16)nArg;

85415    pBest->iPrefEnc = enc;

85416    memcpy(pBest->zName, zName, nName);

85417    pBest->zName[nName] = 0;

85418    sqlite3FuncDefInsert(&db->aFunc, pBest);

85419  }

85420

85421  if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){

85422    return pBest;

85423  }

85424  return 0;

85425}

If the custom function is not found, the sql statement compiling engine claims that there is no such function.

U see, there are more other thing it may claim, such as wrong number of arguments to function, no such colomn, etc.

By now, look at where to set and trigger the user custom sql function.

In updateDatabase(...) @ MediaProvider.java, sql function triggered on deleting from table files is announced.

757    private static void  MediaProvider::updateDatabase(Context context, SQLiteDatabase db, boolean internal,

758            int fromVersion, int toVersion) {

1602        if (fromVersion < 304 && !internal) {

1603            // notifies host when files are deleted

1604            db.execSQL("CREATE TRIGGER IF NOT EXISTS files_cleanup DELETE ON files" + ****************

1605                    "BEGIN " +

1606                        "SELECT _OBJECT_REMOVED(old._id);" +

1607                    "END");

1608

1609        }

1610

1733        if (fromVersion < 506) {

1734            // sd card storage got moved to /storage/sdcard0

1735            // first delete everything that already got scanned in /storage before this

1736            // update step was added

1737            db.execSQL("DROP TRIGGER IF EXISTS files_cleanup");

1738            db.execSQL("DELETE FROM files WHERE _data LIKE '/storage/%';");

1739            db.execSQL("DELETE FROM album_art WHERE _data LIKE '/storage/%';");

1740            db.execSQL("DELETE FROM thumbnails WHERE _data LIKE '/storage/%';");

1741            db.execSQL("DELETE FROM videothumbnails WHERE _data LIKE '/storage/%';");

1742            // then rename everything from /mnt/sdcard/ to /storage/sdcard0,

1743            // and from /mnt/external1 to /storage/sdcard1

1744            db.execSQL("UPDATE files SET " +

1745                "_data='/storage/sdcard0'||SUBSTR(_data,12) WHERE _data LIKE '/mnt/sdcard/%';");

1746            db.execSQL("UPDATE files SET " +

1747                "_data='/storage/sdcard1'||SUBSTR(_data,15) WHERE _data LIKE '/mnt/external1/%';");

1748            db.execSQL("UPDATE album_art SET " +

1749                "_data='/storage/sdcard0'||SUBSTR(_data,12) WHERE _data LIKE '/mnt/sdcard/%';");

1750            db.execSQL("UPDATE album_art SET " +

1751                "_data='/storage/sdcard1'||SUBSTR(_data,15) WHERE _data LIKE '/mnt/external1/%';");

1752            db.execSQL("UPDATE thumbnails SET " +

1753                "_data='/storage/sdcard0'||SUBSTR(_data,12) WHERE _data LIKE '/mnt/sdcard/%';");

1754            db.execSQL("UPDATE thumbnails SET " +

1755                "_data='/storage/sdcard1'||SUBSTR(_data,15) WHERE _data LIKE '/mnt/external1/%';");

1756            db.execSQL("UPDATE videothumbnails SET " +

1757                "_data='/storage/sdcard0'||SUBSTR(_data,12) WHERE _data LIKE '/mnt/sdcard/%';");

1758            db.execSQL("UPDATE videothumbnails SET " +

1759                "_data='/storage/sdcard1'||SUBSTR(_data,15) WHERE _data LIKE '/mnt/external1/%';");

1760

1761            if (!internal) {

1762                db.execSQL("CREATE TRIGGER IF NOT EXISTS files_cleanup DELETE ON files" + ***************8

1763                    "BEGIN " +

1764                        "SELECT _OBJECT_REMOVED(old._id);" +

1765                    "END");

1766            }

1767        }

In onOpen(...) @ MediaProvider.java, the callback function is actually set in host language scope.

436        @Override

437        public void DatabaseHelper::onOpen(SQLiteDatabase db) {

438

439            if (mInternal) return;  // The internal database is kept separately.

440

441            if (mEarlyUpgrade) return; // Doing early upgrade.

442

443            if (mObjectRemovedCallback != null) {

444                db.addCustomFunction("_OBJECT_REMOVED", 1, mObjectRemovedCallback);  *************

445            }

               .....

507        }

So, if here is the cause, _OBJECT_REMOVED customed function is not set for the reason mObjectRemovedCallback is null except the reason that the sqlite customed function hash table is corrupted.

In another database open function, open() @ SQLiteConnection.java, costum functions are not registerred. This is the root cause with more possibility.

208    private void open() {

209        mConnectionPtr = nativeOpen(mConfiguration.path, mConfiguration.openFlags,

210                mConfiguration.label,

211                SQLiteDebug.DEBUG_SQL_STATEMENTS, SQLiteDebug.DEBUG_SQL_TIME);

212

213        setPageSize();

214        setForeignKeyModeFromConfiguration();

215        setWalModeFromConfiguration();

216        setJournalSizeLimit();

217        setAutoCheckpointInterval();

218        setLocaleFromConfiguration();

219    }

It should be patched with lines #219--#225 to register custom functions.

208    private void open() {

209        mConnectionPtr = nativeOpen(mConfiguration.path, mConfiguration.openFlags,

210                mConfiguration.label,

211                SQLiteDebug.DEBUG_SQL_STATEMENTS, SQLiteDebug.DEBUG_SQL_TIME);

212

213        setPageSize();

214        setForeignKeyModeFromConfiguration();

215        setWalModeFromConfiguration();

216        setJournalSizeLimit();

217        setAutoCheckpointInterval();

218        setLocaleFromConfiguration();

219

220        // Register custom functions.

221        final int functionCount = mConfiguration.customFunctions.size();

222        for (int i = 0; i < functionCount; i++) {

223            SQLiteCustomFunction function = mConfiguration.customFunctions.get(i);

224            nativeRegisterCustomFunction(mConnectionPtr, function);

225        }

226    }