Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add APIs to allow fts5 to be augmented with ranking and snippet functions. Does not work yet. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | matchinfo |
Files: | files | file ages | folders |
SHA1: |
a235305d42ed0b17be6e18d4932d9704 |
User & Date: | dan 2013-01-01 19:56:04 |
Context
2013-01-02
| ||
20:01 | Add an implementation of BM25 to fts5func.c. Other changes to matchinfo related things. check-in: 03f26d8c60 user: dan tags: matchinfo | |
2013-01-01
| ||
19:56 | Add APIs to allow fts5 to be augmented with ranking and snippet functions. Does not work yet. check-in: a235305d42 user: dan tags: matchinfo | |
18:41 | Fix a memory leak in fts5.c. check-in: 7bc0e58875 user: dan tags: trunk | |
Changes
Changes to src/expr.c.
2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 |
pColl = sqlite4ExprCollSeq(pParse, pFarg->a[i].pExpr); } } if( pDef->flags & SQLITE4_FUNC_NEEDCOLL ){ if( !pColl ) pColl = db->pDfltColl; sqlite4VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } sqlite4VdbeAddOp4(v, OP_Function, constMask, r1, target, (char*)pDef, P4_FUNCDEF); sqlite4VdbeChangeP5(v, (u8)nFarg); if( nFarg ){ sqlite4ReleaseTempRange(pParse, r1, nFarg); } break; |
> > > |
2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 |
pColl = sqlite4ExprCollSeq(pParse, pFarg->a[i].pExpr); } } if( pDef->flags & SQLITE4_FUNC_NEEDCOLL ){ if( !pColl ) pColl = db->pDfltColl; sqlite4VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } if( pDef->bMatchinfo ){ sqlite4VdbeAddOp1(v, OP_Mifunction, pFarg->a[0].pExpr->iTable); } sqlite4VdbeAddOp4(v, OP_Function, constMask, r1, target, (char*)pDef, P4_FUNCDEF); sqlite4VdbeChangeP5(v, (u8)nFarg); if( nFarg ){ sqlite4ReleaseTempRange(pParse, r1, nFarg); } break; |
Changes to src/fts5.c.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 ... 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 ... 758 759 760 761 762 763 764 765 766 767 768 769 770 771 ... 813 814 815 816 817 818 819 820 821 822 823 824 825 826 ... 886 887 888 889 890 891 892 893 894 895 896 897 898 899 .... 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 |
** expr := expr NOT expr ** expr := expr AND expr ** expr := expr OR expr ** expr := LP expr RP */ /* ** Context object used by expression parser. */ typedef struct Fts5Expr Fts5Expr; typedef struct Fts5ExprNode Fts5ExprNode; typedef struct Fts5List Fts5List; typedef struct Fts5Parser Fts5Parser; typedef struct Fts5ParserToken Fts5ParserToken; typedef struct Fts5Phrase Fts5Phrase; ................................................................................ Fts5ExprNode *pRight; const u8 *aPk; /* Primary key of current entry (or null) */ int nPk; /* Size of aPk[] in bytes */ }; struct Fts5Expr { Fts5ExprNode *pRoot; }; /* ** FTS5 specific cursor data. */ struct Fts5Cursor { sqlite4 *db; Fts5Info *pInfo; Fts5Expr *pExpr; /* MATCH expression for this cursor */ KVByteArray *aKey; /* Buffer for primary key */ int nKeyAlloc; /* Bytes allocated at aKey[] */ }; /* ** This type is used when reading (decoding) an instance-list. */ typedef struct InstanceList InstanceList; struct InstanceList { ................................................................................ int nCol, /* Size of array azCol[] */ const char *zExpr, /* FTS expression text */ Fts5Expr **ppExpr, /* OUT: Expression object */ char **pzErr /* OUT: Error message */ ){ int rc = SQLITE4_OK; Fts5Parser sParse; int nExpr; int i; Fts5Expr *pExpr; int nHier = 0; int nHierAlloc = 0; ExprHier *aHier = 0; ................................................................................ rc = SQLITE4_NOMEM; }else{ pNode->eType = TOKEN_PRIMITIVE; pNode->pPhrase = pPhrase; *pp = pNode; } } break; } case TOKEN_AND: case TOKEN_OR: case TOKEN_NOT: { Fts5ExprNode **pp = aHier[nHier-1].ppNode; ................................................................................ if( aHier[i].nOpen>0 ) rc = SQLITE4_ERROR; } if( rc!=SQLITE4_OK ){ fts5ExpressionFree(db, pExpr); *pzErr = sParse.zErr; }else{ *ppExpr = pExpr; } sqlite4DbFree(db, aHier); return rc; } /* ................................................................................ i = putVarint32(pCsr->aKey, iTbl); memcpy(&pCsr->aKey[i], aPk, nPk); *paKey = pCsr->aKey; *pnKey = nReq; return SQLITE4_OK; } /************************************************************************** *************************************************************************** ** Below this point is test code. */ #ifdef SQLITE4_TEST static int fts5PrintExprNode(sqlite4 *, const char **, Fts5ExprNode *, char **); |
| > > < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 ... 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 ... 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 ... 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 ... 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 .... 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 |
** expr := expr NOT expr ** expr := expr AND expr ** expr := expr OR expr ** expr := LP expr RP */ /* ** Structure types used by this module. */ typedef struct Fts5Expr Fts5Expr; typedef struct Fts5ExprNode Fts5ExprNode; typedef struct Fts5List Fts5List; typedef struct Fts5Parser Fts5Parser; typedef struct Fts5ParserToken Fts5ParserToken; typedef struct Fts5Phrase Fts5Phrase; ................................................................................ Fts5ExprNode *pRight; const u8 *aPk; /* Primary key of current entry (or null) */ int nPk; /* Size of aPk[] in bytes */ }; struct Fts5Expr { Fts5ExprNode *pRoot; int nPhrase; /* Number of Fts5Str objects in query */ Fts5Str **apPhrase; }; /* ** FTS5 specific cursor data. */ struct Fts5Cursor { sqlite4 *db; Fts5Info *pInfo; Fts5Expr *pExpr; /* MATCH expression for this cursor */ KVByteArray *aKey; /* Buffer for primary key */ int nKeyAlloc; /* Bytes allocated at aKey[] */ KVCursor *pCsr; /* Cursor used to retrive values */ Mem *aMem; /* Array of column values */ }; /* ** This type is used when reading (decoding) an instance-list. */ typedef struct InstanceList InstanceList; struct InstanceList { ................................................................................ int nCol, /* Size of array azCol[] */ const char *zExpr, /* FTS expression text */ Fts5Expr **ppExpr, /* OUT: Expression object */ char **pzErr /* OUT: Error message */ ){ int rc = SQLITE4_OK; Fts5Parser sParse; int nStr = 0; int nExpr; int i; Fts5Expr *pExpr; int nHier = 0; int nHierAlloc = 0; ExprHier *aHier = 0; ................................................................................ rc = SQLITE4_NOMEM; }else{ pNode->eType = TOKEN_PRIMITIVE; pNode->pPhrase = pPhrase; *pp = pNode; } } nStr++; break; } case TOKEN_AND: case TOKEN_OR: case TOKEN_NOT: { Fts5ExprNode **pp = aHier[nHier-1].ppNode; ................................................................................ if( aHier[i].nOpen>0 ) rc = SQLITE4_ERROR; } if( rc!=SQLITE4_OK ){ fts5ExpressionFree(db, pExpr); *pzErr = sParse.zErr; }else{ pExpr->nPhrase = nStr; *ppExpr = pExpr; } sqlite4DbFree(db, aHier); return rc; } /* ................................................................................ i = putVarint32(pCsr->aKey, iTbl); memcpy(&pCsr->aKey[i], aPk, nPk); *paKey = pCsr->aKey; *pnKey = nReq; return SQLITE4_OK; } int sqlite4_mi_column_count(sqlite4_context *pCtx, int *pnCol){ int rc = SQLITE4_OK; if( pCtx->pFts ){ *pnCol = pCtx->pFts->pInfo->nCol; }else{ rc = SQLITE4_MISUSE; } return rc; } int sqlite4_mi_column_size(sqlite4_context *pCtx, int iCol, int *pnToken){ int rc = SQLITE4_OK; if( pCtx->pFts ){ }else{ rc = SQLITE4_MISUSE; } return rc; } int sqlite4_mi_column_value( sqlite4_context *pCtx, int iCol, sqlite4_value **ppVal ){ int rc = SQLITE4_OK; if( pCtx->pFts ){ }else{ rc = SQLITE4_MISUSE; } return rc; } int sqlite4_mi_phrase_count(sqlite4_context *pCtx, int *pnPhrase){ int rc = SQLITE4_OK; if( pCtx->pFts ){ *pnPhrase = pCtx->pFts->pExpr->nPhrase; }else{ rc = SQLITE4_MISUSE; } return rc; } int sqlite4_mi_match_count( sqlite4_context *pCtx, int iCol, int iPhrase, int *pnMatch ){ int rc = SQLITE4_OK; if( pCtx->pFts ){ }else{ rc = SQLITE4_MISUSE; } return rc; } int sqlite4_mi_match_offset( sqlite4_context *pCtx, int iCol, int iPhrase, int iMatch, int *piOff ){ } int sqlite4_mi_total_match_count( sqlite4_context *pCtx, int iCol, int iPhrase, int *pnMatch, int *pnDoc ){ } int sqlite4_mi_total_size(sqlite4_context *pCtx, int iCol, int *pnToken){ } int sqlite4_mi_total_count(sqlite4_context *pCtx, int *pnRow){ } /************************************************************************** *************************************************************************** ** Below this point is test code. */ #ifdef SQLITE4_TEST static int fts5PrintExprNode(sqlite4 *, const char **, Fts5ExprNode *, char **); |
Changes to src/fts5func.c.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 .. 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 .. 71 72 73 74 75 76 77 78 79 80 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* */ #include "sqliteInt.h" static int fts5SimpleCreate( void *pCtx, const char **azArg, int nArg, sqlite4_tokenizer **pp ){ ................................................................................ return SQLITE4_OK; } static int fts5SimpleDestroy(sqlite4_tokenizer *p){ return SQLITE4_OK; } static char fts5Tolower(char c){ if( c>='A' && c<='Z' ) c = c + ('a' - 'A'); return c; } static int fts5SimpleTokenize( void *pCtx, sqlite4_tokenizer *p, const char *zDoc, int nDoc, ................................................................................ sqlite4_env *pEnv = sqlite4_db_env(db); rc = sqlite4_create_tokenizer(db, "simple", (void *)pEnv, fts5SimpleCreate, fts5SimpleTokenize, fts5SimpleDestroy ); if( rc!=SQLITE4_OK ) return rc; return rc; } |
> > > > > | | | > > > > > > > |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 .. 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 .. 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* */ #include "sqliteInt.h" static char fts5Tolower(char c){ if( c>='A' && c<='Z' ) c = c + ('a' - 'A'); return c; } static int fts5SimpleCreate( void *pCtx, const char **azArg, int nArg, sqlite4_tokenizer **pp ){ ................................................................................ return SQLITE4_OK; } static int fts5SimpleDestroy(sqlite4_tokenizer *p){ return SQLITE4_OK; } static void fts5Rank(sqlite4_context *pCtx, int nArg, sqlite4_value **apArg){ } static void fts5Snippet(sqlite4_context *pCtx, int nArg, sqlite4_value **apArg){ } static int fts5SimpleTokenize( void *pCtx, sqlite4_tokenizer *p, const char *zDoc, int nDoc, ................................................................................ sqlite4_env *pEnv = sqlite4_db_env(db); rc = sqlite4_create_tokenizer(db, "simple", (void *)pEnv, fts5SimpleCreate, fts5SimpleTokenize, fts5SimpleDestroy ); if( rc!=SQLITE4_OK ) return rc; rc = sqlite4_create_mi_function(db, "rank", 0, SQLITE4_UTF8, 0, fts5Rank, 0); if( rc!=SQLITE4_OK ) return rc; rc = sqlite4_create_mi_function( db, "snippet", -1, SQLITE4_UTF8, 0, fts5Snippet, 0 ); return rc; } |
Changes to src/main.c.
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 |
if( pArg && pArg->nRef==0 ){ assert( rc!=SQLITE4_OK ); xDestroy(p); sqlite4DbFree(db, pArg); } out: rc = sqlite4ApiExit(db, rc); sqlite4_mutex_leave(db->mutex); return rc; } #ifndef SQLITE4_OMIT_UTF16 int sqlite4_create_function16( |
> > > > > > > > > > > > > > > > > > > > > > > > |
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 |
if( pArg && pArg->nRef==0 ){ assert( rc!=SQLITE4_OK ); xDestroy(p); sqlite4DbFree(db, pArg); } out: rc = sqlite4ApiExit(db, rc); sqlite4_mutex_leave(db->mutex); return rc; } int sqlite4_create_mi_function( sqlite4 *db, const char *zFunc, int nArg, int enc, void *p, void (*xFunc)(sqlite4_context*,int,sqlite4_value **), void (*xDestroy)(void *) ){ int rc; int n; n = nArg + (nArg>=0); sqlite4_mutex_enter(db->mutex); rc = sqlite4_create_function_v2(db, zFunc, n, enc, p, xFunc, 0,0,xDestroy); if( rc==SQLITE4_OK ){ FuncDef *p = sqlite4FindFunction(db, zFunc, -1, n, enc, 0); p->bMatchinfo = 1; } rc = sqlite4ApiExit(db, rc); sqlite4_mutex_leave(db->mutex); return rc; } #ifndef SQLITE4_OMIT_UTF16 int sqlite4_create_function16( |
Changes to src/resolve.c.
431
432
433
434
435
436
437
438
439
440
441
442
443
444
...
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
|
testcase( iCol==BMS );
testcase( iCol==BMS-1 );
pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
ExprSetProperty(p, EP_Resolved);
}
return p;
}
static void resolveMatch(Parse *pParse, NameContext *pNC, Expr *pExpr){
Expr *pLeft = pExpr->pLeft;
SrcList *pSrc = pNC->pSrcList;
SrcListItem *pItem;
char *zLhs;
int i;
................................................................................
nId, zId);
pNC->nErr++;
}
if( is_agg ){
pExpr->op = TK_AGG_FUNCTION;
pNC->hasAgg = 1;
}
if( is_agg ) pNC->allowAgg = 0;
sqlite4WalkExprList(pWalker, pList);
if( is_agg ) pNC->allowAgg = 1;
/* FIX ME: Compute pExpr->affinity based on the expected return
** type of the function
*/
return WRC_Prune;
}
#ifndef SQLITE4_OMIT_SUBQUERY
case TK_SELECT:
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
...
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
|
testcase( iCol==BMS ); testcase( iCol==BMS-1 ); pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol); ExprSetProperty(p, EP_Resolved); } return p; } static void resolveMatchArg(Parse *pParse, NameContext *pNC, Expr *pExpr){ SrcList *pSrc = pNC->pSrcList; SrcListItem *pItem; char *zLhs; int i; Index *pIdx; if( pExpr->op!=TK_ID || pSrc==0 || pExpr==0 ){ sqlite4ErrorMsg(pParse, "first argument xxx must be a table name"); return; } zLhs = pExpr->u.zToken; for(i=0; i<pSrc->nSrc; i++){ pItem = &pSrc->a[i]; if( pItem->zAlias && sqlite4StrICmp(zLhs, pItem->zAlias)==0 ) break; if( pItem->zAlias==0 && sqlite4StrICmp(zLhs, pItem->zName)==0 ) break; } if( i==pSrc->nSrc ){ sqlite4ErrorMsg(pParse, "no such table: %s", zLhs); return; } pExpr->op = TK_NULL; pExpr->iTable = pItem->iCursor; ExprSetProperty(pExpr, EP_Resolved); } static void resolveMatch(Parse *pParse, NameContext *pNC, Expr *pExpr){ Expr *pLeft = pExpr->pLeft; SrcList *pSrc = pNC->pSrcList; SrcListItem *pItem; char *zLhs; int i; ................................................................................ nId, zId); pNC->nErr++; } if( is_agg ){ pExpr->op = TK_AGG_FUNCTION; pNC->hasAgg = 1; } if( pParse->nErr==0 ){ if( pDef->bMatchinfo ){ resolveMatchArg(pParse, pNC, n>0 ? pList->a[0].pExpr : 0); } if( is_agg ) pNC->allowAgg = 0; sqlite4WalkExprList(pWalker, pList); if( is_agg ) pNC->allowAgg = 1; } /* FIX ME: Compute pExpr->affinity based on the expected return ** type of the function */ return WRC_Prune; } #ifndef SQLITE4_OMIT_SUBQUERY case TK_SELECT: |
Changes to src/sqlite.h.in.
4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 |
const char*, int, int(*x)(void *ctx, int iWeight, int iOff, const char *zToken, int nToken, int iSrc, int nSrc) ), int (*xDestroy)(sqlite4_tokenizer *) ); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE4_OMIT_FLOATING_POINT # undef double #endif #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 |
const char*, int, int(*x)(void *ctx, int iWeight, int iOff, const char *zToken, int nToken, int iSrc, int nSrc) ), int (*xDestroy)(sqlite4_tokenizer *) ); /* ** CAPI4REF: Register a matchinfo function. */ int sqlite4_create_mi_function( sqlite4 *db, const char *zFunc, int nArg, int enc, void *p, void (*xFunc)(sqlite4_context*,int,sqlite4_value **), void (*xDestroy)(void *) ); /* ** Special functions that may be called from within matchinfo UDFs. All ** return an SQLite error code - SQLITE4_OK if successful, or some other ** error code otherwise. ** ** sqlite4_mi_column_count(): ** Set *pnCol to the number of columns in the queried table. ** ** sqlite4_mi_column_size(): ** Set *pnToken to the number of tokens in the value stored in column iCol ** of the current row. ** ** sqlite4_mi_column_value(): ** Set *ppVal to point to an sqlite4_value object containing the value ** read from column iCol of the current row. This object is valid until ** the function callback returns. ** ** sqlite4_mi_phrase_count(): ** Set *pnPhrase to the number of phrases in the query. ** ** sqlite4_mi_match_count(): ** Set *pn to the number of occurences of phrase iPhrase in column iCol of ** the current row. ** ** sqlite4_mi_total_match_count(): ** Set *pnMatch to the total number of occurrences of phrase iPhrase ** in column iCol of all rows in the indexed table. Set *pnDoc to the ** number of rows that contain at least one match for phrase iPhrase in ** column iCol. ** ** sqlite4_mi_match_offset(): ** Set *piOff to the token offset of the iMatch'th instance of phrase ** iPhrase in column iCol of the current row. If any parameter is out ** of range (i.e. too large) it is not an error. In this case *piOff is ** set to -1 before returning. ** ** sqlite4_mi_total_size(): ** Set *pnToken to the total number of tokens in column iCol of all rows ** in the indexed table. ** ** sqlite4_mi_total_count(): ** Set *pnRow to the total number of rows in the indexed table. */ int sqlite4_mi_column_count(sqlite4_context *, int *pnCol); int sqlite4_mi_column_size(sqlite4_context *, int iCol, int *pnToken); int sqlite4_mi_column_value(sqlite4_context *, int iCol, sqlite4_value **ppVal); int sqlite4_mi_phrase_count(sqlite4_context *, int *pnPhrase); int sqlite4_mi_match_count(sqlite4_context *, int iCol, int iPhrase, int *pn); int sqlite4_mi_match_offset( sqlite4_context *, int iCol, int iPhrase, int iMatch, int *piOff); int sqlite4_mi_total_match_count( sqlite4_context *, int iCol, int iPhrase, int *pnMatch, int *pnDoc); int sqlite4_mi_total_size(sqlite4_context *, int iCol, int *pnToken); int sqlite4_mi_total_count(sqlite4_context *, int *pnRow); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE4_OMIT_FLOATING_POINT # undef double #endif #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif |
Changes to src/sqliteInt.h.
635 636 637 638 639 640 641 642 643 644 645 646 647 648 |
FuncDef *pSameName; /* Next with a different name but the same hash */ void (*xFunc)(sqlite4_context*,int,sqlite4_value**); /* Regular function */ void (*xStep)(sqlite4_context*,int,sqlite4_value**); /* Aggregate step */ void (*xFinalize)(sqlite4_context*); /* Aggregate finalizer */ char *zName; /* SQL name of the function. */ FuncDef *pNextName; /* Next function with a different name */ FuncDestructor *pDestructor; /* Reference counted destructor function */ }; /* ** A table of SQL functions. ** ** The content is a linked list of FuncDef structures with branches. When ** there are two or more FuncDef objects with the same name, they are |
> |
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 |
FuncDef *pSameName; /* Next with a different name but the same hash */
void (*xFunc)(sqlite4_context*,int,sqlite4_value**); /* Regular function */
void (*xStep)(sqlite4_context*,int,sqlite4_value**); /* Aggregate step */
void (*xFinalize)(sqlite4_context*); /* Aggregate finalizer */
char *zName; /* SQL name of the function. */
FuncDef *pNextName; /* Next function with a different name */
FuncDestructor *pDestructor; /* Reference counted destructor function */
u8 bMatchinfo; /* True for matchinfo function */
};
/*
** A table of SQL functions.
**
** The content is a linked list of FuncDef structures with branches. When
** there are two or more FuncDef objects with the same name, they are
|
Changes to src/vdbe.c.
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
....
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
|
** to retrieve the collation sequence set by this opcode is not available
** publicly, only to user functions defined in func.c.
*/
case OP_CollSeq: {
assert( pOp->p4type==P4_COLLSEQ );
break;
}
/* Opcode: Function P1 P2 P3 P4 P5
**
** Invoke a user function (P4 is a pointer to a Function structure that
** defines the function) with P5 arguments taken from register P2 and
** successors. The result of the function is stored in register P3.
** Register P3 must not be one of the function inputs.
................................................................................
ctx.pFunc = ctx.pVdbeFunc->pFunc;
}
ctx.s.flags = MEM_Null;
ctx.s.db = db;
ctx.s.xDel = 0;
ctx.s.zMalloc = 0;
/* The output cell may already have a buffer allocated. Move
** the pointer to ctx.s so in case the user-function can use
** the already allocated buffer instead of allocating a new one.
*/
sqlite4VdbeMemMove(&ctx.s, pOut);
MemSetTypeFlag(&ctx.s, MEM_Null);
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
....
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
|
** to retrieve the collation sequence set by this opcode is not available ** publicly, only to user functions defined in func.c. */ case OP_CollSeq: { assert( pOp->p4type==P4_COLLSEQ ); break; } /* Opcode: Mifunction P1 */ case OP_Mifunction: { pc++; pOp++; /* fall through to OP_Function */ }; /* Opcode: Function P1 P2 P3 P4 P5 ** ** Invoke a user function (P4 is a pointer to a Function structure that ** defines the function) with P5 arguments taken from register P2 and ** successors. The result of the function is stored in register P3. ** Register P3 must not be one of the function inputs. ................................................................................ ctx.pFunc = ctx.pVdbeFunc->pFunc; } ctx.s.flags = MEM_Null; ctx.s.db = db; ctx.s.xDel = 0; ctx.s.zMalloc = 0; if( pOp[-1].opcode==OP_Mifunction ){ ctx.pFts = p->apCsr[pOp[-1].p1]->pFts; apVal++; n--; }else{ ctx.pFts = 0; } /* The output cell may already have a buffer allocated. Move ** the pointer to ctx.s so in case the user-function can use ** the already allocated buffer instead of allocating a new one. */ sqlite4VdbeMemMove(&ctx.s, pOut); MemSetTypeFlag(&ctx.s, MEM_Null); |
Changes to src/vdbeInt.h.
237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
struct sqlite4_context { FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */ VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */ Mem s; /* The return value is stored here */ Mem *pMem; /* Memory cell used to store aggregate context */ int isError; /* Error code returned by the function. */ CollSeq *pColl; /* Collating sequence */ }; /* ** An Explain object accumulates indented output which is helpful ** in describing recursive data structures. */ struct Explain { |
> |
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
struct sqlite4_context {
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */
Mem s; /* The return value is stored here */
Mem *pMem; /* Memory cell used to store aggregate context */
int isError; /* Error code returned by the function. */
CollSeq *pColl; /* Collating sequence */
Fts5Cursor *pFts; /* fts5 cursor for matchinfo functions */
};
/*
** An Explain object accumulates indented output which is helpful
** in describing recursive data structures.
*/
struct Explain {
|
Changes to src/where.c.
5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 |
while( pOp<pEnd ){ if( pOp->p1==pLevel->iTabCur && pOp->opcode==OP_Column ){ pOp->p1 = pLevel->iIdxCur; } pOp++; } } } /* Final cleanup */ pParse->nQueryLoop = pWInfo->savedNQueryLoop; whereInfoFree(db, pWInfo); return; } |
> > > > > > > > > > > > > > > > > > |
5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 |
while( pOp<pEnd ){ if( pOp->p1==pLevel->iTabCur && pOp->opcode==OP_Column ){ pOp->p1 = pLevel->iIdxCur; } pOp++; } } if( (pLevel->plan.wsFlags & WHERE_INDEXED) && (pLevel->plan.u.pIdx->eIndexType==SQLITE4_INDEX_FTS5) ){ VdbeOp *pOp; VdbeOp *pEnd; assert( pLevel->iTabCur!=pLevel->iIdxCur ); pOp = sqlite4VdbeGetOp(v, pWInfo->iTop); pEnd = &pOp[sqlite4VdbeCurrentAddr(v) - pWInfo->iTop]; while( pOp<pEnd ){ if( pOp->p1==pLevel->iTabCur && pOp->opcode==OP_Mifunction ){ pOp->p1 = pLevel->iIdxCur; } pOp++; } } } /* Final cleanup */ pParse->nQueryLoop = pWInfo->savedNQueryLoop; whereInfoFree(db, pWInfo); return; } |
Changes to test/fts5create.test.
whitespace changes only
Changes to test/fts5query1.test.
130 131 132 133 134 135 136 137 138 139 |
2 {a:a} {1} 3 {b:a} {2} 4 {c:a} {1 2} 5 {a:a*} {1} } { do_execsql_test 7.$tn {SELECT docid FROM t7 WHERE t7 MATCH $expr} $res } finish_test |
> > > > > > > > > > > > > |
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
2 {a:a} {1} 3 {b:a} {2} 4 {c:a} {1 2} 5 {a:a*} {1} } { do_execsql_test 7.$tn {SELECT docid FROM t7 WHERE t7 MATCH $expr} $res } #------------------------------------------------------------------------- # do_execsql_test 8.0 { CREATE TABLE t8(a PRIMARY KEY, b, c); CREATE INDEX i8 ON t8 USING fts5(); INSERT INTO t8 VALUES('one', 'a b c', 'a a a'); INSERT INTO t8 VALUES('two', 'd e f', 'b b b'); } do_execsql_test 8.1 { SELECT rank(t8) FROM t8 WHERE t8 MATCH 'b a' } finish_test |