sqlite3 engine claims no such function when compiling sql statement

来源:互联网 发布:cloudtv mac 编辑:程序博客网 时间:2024/06/07 00:15

本文介绍了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,              /* Database handle. */
94514  const void *zSql,         /* UTF-16 encoded SQL statement. */
94515  int nBytes,               /* Length of zSql in bytes. */
94516  sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
94517  const void **pzTail       /* OUT: End of parsed string */
94518){
94519  int rc;
94520  rc = sqlite3Prepare16(db,zSql,nBytes,1,ppStmt,pzTail);
94521  assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 );  /* VERIFY: F13021 */
94522  return rc;
94523}

calls------->>

94450static int sqlite3Prepare16(
94451  sqlite3 *db,              /* Database handle. */
94452  const void *zSql,         /* UTF-16 encoded SQL statement. */
94453  int nBytes,               /* Length of zSql in bytes. */
94454  int saveSqlFlag,          /* True to save SQL text into the sqlite3_stmt */
94455  sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
94456  const void **pzTail       /* OUT: End of parsed string */
94457){
94458  /* This function currently works by first transforming the UTF-16
94459  ** encoded string to UTF-8, then invoking sqlite3_prepare(). The
94460  ** tricky bit is figuring out the pointer to return in *pzTail.
94461  */
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    /* If sqlite3_prepare returns a tail pointer, we calculate the
94479    ** equivalent pointer into the UTF-16 string by counting the unicode
94480    ** characters between zSql8 and zTail8, and then returning a pointer
94481    ** the same number of characters into the UTF-16 string.
94482    */
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,              /* Database handle. */
94350  const char *zSql,         /* UTF-8 encoded SQL statement. */
94351  int nBytes,               /* Length of zSql in bytes. */
94352  int saveSqlFlag,          /* True to copy SQL text into the sqlite3_stmt */
94353  Vdbe *pOld,               /* VM being reprepared */
94354  sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
94355  const char **pzTail       /* OUT: End of parsed string */
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/*
94186** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
94187*/
94188static int sqlite3Prepare(
94189  sqlite3 *db,              /* Database handle. */
94190  const char *zSql,         /* UTF-8 encoded SQL statement. */
94191  int nBytes,               /* Length of zSql in bytes. */
94192  int saveSqlFlag,          /* True to copy SQL text into the sqlite3_stmt */
94193  Vdbe *pReprepare,         /* VM being reprepared */
94194  sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
94195  const char **pzTail       /* OUT: End of parsed string */
94196){
94197  Parse *pParse;            /* Parsing context */
94198  char *zErrMsg = 0;        /* Error message */
94199  int rc = SQLITE_OK;       /* Result code */
94200  int i;                    /* Loop counter */
94201
94202  /* Allocate the parsing context */
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  /* Check to verify that it is possible to get a read lock on all
94214  ** database schemas.  The inability to get a read lock indicates that
94215  ** some other database connection is holding a write-lock, which in
94216  ** turn means that the other connection has made uncommitted changes
94217  ** to the schema.
94218  **
94219  ** Were we to proceed and prepare the statement against the uncommitted
94220  ** schema changes and if those schema changes are subsequently rolled
94221  ** back and different changes are made in their place, then when this
94222  ** prepared statement goes to run the schema cookie would fail to detect
94223  ** the schema change.  Disaster would follow.
94224  **
94225  ** This thread is currently holding mutexes on all Btrees (because
94226  ** of the sqlite3BtreeEnterAll() in sqlite3LockAndPrepare()) so it
94227  ** is not possible for another thread to start a new schema change
94228  ** while this routine is running.  Hence, we do not need to hold
94229  ** locks on the schema, we just need to make sure nobody else is
94230  ** holding them.
94231  **
94232  ** Note that setting READ_UNCOMMITTED overrides most lock detection,
94233  ** but it does *not* override schema lock detection, so this all still
94234  ** works even if READ_UNCOMMITTED is set.
94235  */
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  /* Delete any TriggerPrg structures allocated while parsing this statement. */
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,       /* Namespace to resolve expressions in. */
74342  Expr *pExpr             /* The expression to be analyzed. */
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,         /* The parser context */
74393  Select *p,             /* The SELECT statement being coded. */
74394  NameContext *pOuterNC  /* Name context for parent SELECT statement */
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    /* The special operator TK_ROW means use the rowid for the first
73649    ** column in the FROM clause.  This is used by the LIMIT and ORDER BY
73650    ** clause processing on UPDATE and DELETE statements.
73651    */
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 /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
73665
73666    /* A lone identifier is the name of a column.
73667    */
73668    case TK_ID: {
73669      return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr);
73670    }
73671
73672    /* A table name and column name:     ID.ID
73673    ** Or a database, table and column:  ID.ID.ID
73674    */
73675    case TK_DOT: {
73676      const char *zColumn;
73677      const char *zTable;
73678      const char *zDb;
73679      Expr *pRight;
73680
73681      /* if( pSrcList==0 ) break; */
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    /* Resolve function names
73697    */
73698    case TK_CONST_FUNC:
73699    case TK_FUNCTION: {
73700      ExprList *pList = pExpr->x.pList;    /* The argument list */
73701      int n = pList ? pList->nExpr : 0;    /* Number of arguments */
73702      int no_such_func = 0;       /* True if no such function exists */
73703      int wrong_num_args = 0;     /* True if wrong number of arguments */
73704      int is_agg = 0;             /* True if is an aggregate function */
73705      int auth;                   /* Authorization to use the function */
73706      int nId;                    /* Number of characters in function name */
73707      const char *zId;            /* The function name. */
73708      FuncDef *pDef;              /* Information about the function */
73709      u8 enc = ENC(pParse->db);   /* The database encoding */
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      /* FIX ME:  Compute pExpr->affinity based on the expected return
73760      ** type of the function
73761      */
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/*
85333** Locate a user function given a name, a number of arguments and a flag
85334** indicating whether the function prefers UTF-16 over UTF-8.  Return a
85335** pointer to the FuncDef structure that defines that function, or return
85336** NULL if the function does not exist.
85337**
85338** If the createFlag argument is true, then a new (blank) FuncDef
85339** structure is created and liked into the "db" structure if a
85340** no matching function previously existed.  When createFlag is true
85341** and the nArg parameter is -1, then only a function that accepts
85342** any number of arguments will be returned.
85343**
85344** If createFlag is false and nArg is -1, then the first valid
85345** function found is returned.  A function is valid if either xFunc
85346** or xStep is non-zero.
85347**
85348** If createFlag is false, then a function with the required name and
85349** number of arguments may be returned even if the eTextRep flag does not
85350** match that requested.
85351*/
85352SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
85353  sqlite3 *db,       /* An open database */
85354  const char *zName, /* Name of the function.  Not null-terminated */
85355  int nName,         /* Number of characters in the name */
85356  int nArg,          /* Number of arguments.  -1 means any number */
85357  u8 enc,            /* Preferred text encoding */
85358  int createFlag     /* Create new entry if true and does not otherwise exist */
85359){
85360  FuncDef *p;         /* Iterator variable */
85361  FuncDef *pBest = 0; /* Best match found so far */
85362  int bestScore = 0;  /* Score of best match */
85363  int h;              /* Hash value */
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  /* First search for a match amongst the application-defined functions.
85370  */
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  /* If no match is found, search the built-in functions.
85382  **
85383  ** If the SQLITE_PreferBuiltin flag is set, then search the built-in
85384  ** functions even if a prior app-defined function was found.  And give
85385  ** priority to built-in functions.
85386  **
85387  ** Except, if createFlag is true, that means that we are trying to
85388  ** install a new function.  Whatever FuncDef structure is returned it will
85389  ** have fields overwritten with new information appropriate for the
85390  ** new function.  But the FuncDefs for built-in functions are read-only.
85391  ** So we must not search for built-ins when creating a new function.
85392  */
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  /* If the createFlag parameter is true and the search did not reveal an
85408  ** exact match for the name, number of arguments and encoding, then add a
85409  ** new entry to the hash table and return it.
85410  */
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    }

原创粉丝点击