sqlite3 engine claims no such function when compiling sql statement

前端之家收集整理的这篇文章主要介绍了sqlite3 engine claims no such function when compiling sql statement前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_404_0@本文介绍了sqlite3解析和编译sql语句时,宿主语言设置的定制函数找不到的issue; 主要引用相关代码,描述了sqlite编译sql语句的大致流程.

@H_404_0@[GENERAL DESCRIPTION:]

@H_404_0@Process: com.sonyericsson.album
Flags: 0x8be45
Package: com.xxxxxxxxx.album
Build: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:userdebug/release-keys

@H_404_0@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

@H_404_0@[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}

@H_404_0@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}

@H_404_0@calls------->>

@H_404_0@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,sqlITE_UTF16NATIVE);
94473 if( zsql8 ){
94474 rc = sqlite3LockAndPrepare(db,zsql8,-1,savesqlFlag,&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,pOld,pzTail);
94366 if( rc==sqlITE_SCHEMA ){
94367 sqlite3_finalize(*ppStmt);
94368 rc = sqlite3Prepare(db,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,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,&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,(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,"%s",zErrMsg);
94329 sqlite3DbFree(db,zErrMsg);
94330 }else{
94331 sqlite3Error(db,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}

@H_404_0@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 /

@H_404_0@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.

@H_404_0@In this issue,the DELETE is compiled by sqlite3DeleteFrom(...) which calls sqlite3ResolveExprNames.
The source of sqlite3ResolveExprNames & sqlite3ResolveSelectNames list as follows.

@H_404_0@============================================================================================
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}
===========================================================================================

@H_404_0@sqlite3ResolveExprNames(...) uses sqlite3WalkExpr(...) with worker callbacks to resolve expression names.
The ExprCallback field is resolveExprStep(...).

@H_404_0@The source of resolveExprStep(...) is following.
Notice the first line comment of the function,it is callback for sqlite3WalkExpr().

@H_404_0@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,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,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,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,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()",zId);
73742 pNC->nErr++;
73743 is_agg = 0;
73744 }else if( no_such_func ){
73745 sqlite3ErrorMsg(pParse,"no such function: %.*s",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}

@H_404_0@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,nName);
85397 while( p ){
85398 int score = matchQuality(p,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,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}

@H_404_0@Ifthe 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.

@H_404_0@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) {

@H_404_0@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

@H_404_0@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 }

@H_404_0@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",mObjectRemovedCallback); *************
445 }
.....
507 }

@H_404_0@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.

@H_404_0@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,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 }

猜你在找的Sqlite相关文章