OLD | NEW |
1 /* | 1 /* |
2 ** 2015 May 08 | 2 ** 2015 May 08 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 int nByte; /* Bytes of space to allocate */ | 177 int nByte; /* Bytes of space to allocate */ |
178 const char *zDb = bDb ? argv[3] : argv[1]; | 178 const char *zDb = bDb ? argv[3] : argv[1]; |
179 const char *zTab = bDb ? argv[4] : argv[3]; | 179 const char *zTab = bDb ? argv[4] : argv[3]; |
180 const char *zType = bDb ? argv[5] : argv[4]; | 180 const char *zType = bDb ? argv[5] : argv[4]; |
181 int nDb = (int)strlen(zDb)+1; | 181 int nDb = (int)strlen(zDb)+1; |
182 int nTab = (int)strlen(zTab)+1; | 182 int nTab = (int)strlen(zTab)+1; |
183 int eType = 0; | 183 int eType = 0; |
184 | 184 |
185 rc = fts5VocabTableType(zType, pzErr, &eType); | 185 rc = fts5VocabTableType(zType, pzErr, &eType); |
186 if( rc==SQLITE_OK ){ | 186 if( rc==SQLITE_OK ){ |
187 assert( eType>=0 && eType<sizeof(azSchema)/sizeof(azSchema[0]) ); | 187 assert( eType>=0 && eType<ArraySize(azSchema) ); |
188 rc = sqlite3_declare_vtab(db, azSchema[eType]); | 188 rc = sqlite3_declare_vtab(db, azSchema[eType]); |
189 } | 189 } |
190 | 190 |
191 nByte = sizeof(Fts5VocabTable) + nDb + nTab; | 191 nByte = sizeof(Fts5VocabTable) + nDb + nTab; |
192 pRet = sqlite3Fts5MallocZero(&rc, nByte); | 192 pRet = sqlite3Fts5MallocZero(&rc, nByte); |
193 if( pRet ){ | 193 if( pRet ){ |
194 pRet->pGlobal = (Fts5Global*)pAux; | 194 pRet->pGlobal = (Fts5Global*)pAux; |
195 pRet->eType = eType; | 195 pRet->eType = eType; |
196 pRet->db = db; | 196 pRet->db = db; |
197 pRet->zFts5Tbl = (char*)&pRet[1]; | 197 pRet->zFts5Tbl = (char*)&pRet[1]; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ | 230 sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ |
231 char **pzErr /* OUT: sqlite3_malloc'd error message */ | 231 char **pzErr /* OUT: sqlite3_malloc'd error message */ |
232 ){ | 232 ){ |
233 return fts5VocabInitVtab(db, pAux, argc, argv, ppVtab, pzErr); | 233 return fts5VocabInitVtab(db, pAux, argc, argv, ppVtab, pzErr); |
234 } | 234 } |
235 | 235 |
236 /* | 236 /* |
237 ** Implementation of the xBestIndex method. | 237 ** Implementation of the xBestIndex method. |
238 */ | 238 */ |
239 static int fts5VocabBestIndexMethod( | 239 static int fts5VocabBestIndexMethod( |
240 sqlite3_vtab *pVTab, | 240 sqlite3_vtab *pUnused, |
241 sqlite3_index_info *pInfo | 241 sqlite3_index_info *pInfo |
242 ){ | 242 ){ |
243 int i; | 243 int i; |
244 int iTermEq = -1; | 244 int iTermEq = -1; |
245 int iTermGe = -1; | 245 int iTermGe = -1; |
246 int iTermLe = -1; | 246 int iTermLe = -1; |
247 int idxNum = 0; | 247 int idxNum = 0; |
248 int nArg = 0; | 248 int nArg = 0; |
249 | 249 |
| 250 UNUSED_PARAM(pUnused); |
| 251 |
250 for(i=0; i<pInfo->nConstraint; i++){ | 252 for(i=0; i<pInfo->nConstraint; i++){ |
251 struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; | 253 struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; |
252 if( p->usable==0 ) continue; | 254 if( p->usable==0 ) continue; |
253 if( p->iColumn==0 ){ /* term column */ | 255 if( p->iColumn==0 ){ /* term column */ |
254 if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ) iTermEq = i; | 256 if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ) iTermEq = i; |
255 if( p->op==SQLITE_INDEX_CONSTRAINT_LE ) iTermLe = i; | 257 if( p->op==SQLITE_INDEX_CONSTRAINT_LE ) iTermLe = i; |
256 if( p->op==SQLITE_INDEX_CONSTRAINT_LT ) iTermLe = i; | 258 if( p->op==SQLITE_INDEX_CONSTRAINT_LT ) iTermLe = i; |
257 if( p->op==SQLITE_INDEX_CONSTRAINT_GE ) iTermGe = i; | 259 if( p->op==SQLITE_INDEX_CONSTRAINT_GE ) iTermGe = i; |
258 if( p->op==SQLITE_INDEX_CONSTRAINT_GT ) iTermGe = i; | 260 if( p->op==SQLITE_INDEX_CONSTRAINT_GT ) iTermGe = i; |
259 } | 261 } |
(...skipping 10 matching lines...) Expand all Loading... |
270 pInfo->aConstraintUsage[iTermGe].argvIndex = ++nArg; | 272 pInfo->aConstraintUsage[iTermGe].argvIndex = ++nArg; |
271 pInfo->estimatedCost = pInfo->estimatedCost / 2; | 273 pInfo->estimatedCost = pInfo->estimatedCost / 2; |
272 } | 274 } |
273 if( iTermLe>=0 ){ | 275 if( iTermLe>=0 ){ |
274 idxNum |= FTS5_VOCAB_TERM_LE; | 276 idxNum |= FTS5_VOCAB_TERM_LE; |
275 pInfo->aConstraintUsage[iTermLe].argvIndex = ++nArg; | 277 pInfo->aConstraintUsage[iTermLe].argvIndex = ++nArg; |
276 pInfo->estimatedCost = pInfo->estimatedCost / 2; | 278 pInfo->estimatedCost = pInfo->estimatedCost / 2; |
277 } | 279 } |
278 } | 280 } |
279 | 281 |
| 282 /* This virtual table always delivers results in ascending order of |
| 283 ** the "term" column (column 0). So if the user has requested this |
| 284 ** specifically - "ORDER BY term" or "ORDER BY term ASC" - set the |
| 285 ** sqlite3_index_info.orderByConsumed flag to tell the core the results |
| 286 ** are already in sorted order. */ |
| 287 if( pInfo->nOrderBy==1 |
| 288 && pInfo->aOrderBy[0].iColumn==0 |
| 289 && pInfo->aOrderBy[0].desc==0 |
| 290 ){ |
| 291 pInfo->orderByConsumed = 1; |
| 292 } |
| 293 |
280 pInfo->idxNum = idxNum; | 294 pInfo->idxNum = idxNum; |
281 | |
282 return SQLITE_OK; | 295 return SQLITE_OK; |
283 } | 296 } |
284 | 297 |
285 /* | 298 /* |
286 ** Implementation of xOpen method. | 299 ** Implementation of xOpen method. |
287 */ | 300 */ |
288 static int fts5VocabOpenMethod( | 301 static int fts5VocabOpenMethod( |
289 sqlite3_vtab *pVTab, | 302 sqlite3_vtab *pVTab, |
290 sqlite3_vtab_cursor **ppCsr | 303 sqlite3_vtab_cursor **ppCsr |
291 ){ | 304 ){ |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ | 385 static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ |
373 Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; | 386 Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; |
374 Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab; | 387 Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab; |
375 int rc = SQLITE_OK; | 388 int rc = SQLITE_OK; |
376 int nCol = pCsr->pConfig->nCol; | 389 int nCol = pCsr->pConfig->nCol; |
377 | 390 |
378 pCsr->rowid++; | 391 pCsr->rowid++; |
379 | 392 |
380 if( pTab->eType==FTS5_VOCAB_COL ){ | 393 if( pTab->eType==FTS5_VOCAB_COL ){ |
381 for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){ | 394 for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){ |
382 if( pCsr->aCnt[pCsr->iCol] ) break; | 395 if( pCsr->aDoc[pCsr->iCol] ) break; |
383 } | 396 } |
384 } | 397 } |
385 | 398 |
386 if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){ | 399 if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){ |
387 if( sqlite3Fts5IterEof(pCsr->pIter) ){ | 400 if( sqlite3Fts5IterEof(pCsr->pIter) ){ |
388 pCsr->bEof = 1; | 401 pCsr->bEof = 1; |
389 }else{ | 402 }else{ |
390 const char *zTerm; | 403 const char *zTerm; |
391 int nTerm; | 404 int nTerm; |
392 | 405 |
393 zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm); | 406 zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm); |
394 if( pCsr->nLeTerm>=0 ){ | 407 if( pCsr->nLeTerm>=0 ){ |
395 int nCmp = MIN(nTerm, pCsr->nLeTerm); | 408 int nCmp = MIN(nTerm, pCsr->nLeTerm); |
396 int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp); | 409 int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp); |
397 if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){ | 410 if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){ |
398 pCsr->bEof = 1; | 411 pCsr->bEof = 1; |
399 return SQLITE_OK; | 412 return SQLITE_OK; |
400 } | 413 } |
401 } | 414 } |
402 | 415 |
403 sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm); | 416 sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm); |
404 memset(pCsr->aCnt, 0, nCol * sizeof(i64)); | 417 memset(pCsr->aCnt, 0, nCol * sizeof(i64)); |
405 memset(pCsr->aDoc, 0, nCol * sizeof(i64)); | 418 memset(pCsr->aDoc, 0, nCol * sizeof(i64)); |
406 pCsr->iCol = 0; | 419 pCsr->iCol = 0; |
407 | 420 |
408 assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); | 421 assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); |
409 while( rc==SQLITE_OK ){ | 422 while( rc==SQLITE_OK ){ |
410 i64 dummy; | |
411 const u8 *pPos; int nPos; /* Position list */ | 423 const u8 *pPos; int nPos; /* Position list */ |
412 i64 iPos = 0; /* 64-bit position read from poslist */ | 424 i64 iPos = 0; /* 64-bit position read from poslist */ |
413 int iOff = 0; /* Current offset within position list */ | 425 int iOff = 0; /* Current offset within position list */ |
414 | 426 |
415 rc = sqlite3Fts5IterPoslist(pCsr->pIter, 0, &pPos, &nPos, &dummy); | 427 pPos = pCsr->pIter->pData; |
416 if( rc==SQLITE_OK ){ | 428 nPos = pCsr->pIter->nData; |
417 if( pTab->eType==FTS5_VOCAB_ROW ){ | 429 switch( pCsr->pConfig->eDetail ){ |
418 while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ | 430 case FTS5_DETAIL_FULL: |
419 pCsr->aCnt[0]++; | 431 pPos = pCsr->pIter->pData; |
420 } | 432 nPos = pCsr->pIter->nData; |
421 pCsr->aDoc[0]++; | 433 if( pTab->eType==FTS5_VOCAB_ROW ){ |
422 }else{ | 434 while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
423 int iCol = -1; | 435 pCsr->aCnt[0]++; |
424 while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ | 436 } |
425 int ii = FTS5_POS2COLUMN(iPos); | 437 pCsr->aDoc[0]++; |
426 pCsr->aCnt[ii]++; | 438 }else{ |
427 if( iCol!=ii ){ | 439 int iCol = -1; |
428 pCsr->aDoc[ii]++; | 440 while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
429 iCol = ii; | 441 int ii = FTS5_POS2COLUMN(iPos); |
| 442 pCsr->aCnt[ii]++; |
| 443 if( iCol!=ii ){ |
| 444 if( ii>=nCol ){ |
| 445 rc = FTS5_CORRUPT; |
| 446 break; |
| 447 } |
| 448 pCsr->aDoc[ii]++; |
| 449 iCol = ii; |
| 450 } |
430 } | 451 } |
431 } | 452 } |
432 } | 453 break; |
| 454 |
| 455 case FTS5_DETAIL_COLUMNS: |
| 456 if( pTab->eType==FTS5_VOCAB_ROW ){ |
| 457 pCsr->aDoc[0]++; |
| 458 }else{ |
| 459 while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){ |
| 460 assert_nc( iPos>=0 && iPos<nCol ); |
| 461 if( iPos>=nCol ){ |
| 462 rc = FTS5_CORRUPT; |
| 463 break; |
| 464 } |
| 465 pCsr->aDoc[iPos]++; |
| 466 } |
| 467 } |
| 468 break; |
| 469 |
| 470 default: |
| 471 assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE ); |
| 472 pCsr->aDoc[0]++; |
| 473 break; |
| 474 } |
| 475 |
| 476 if( rc==SQLITE_OK ){ |
433 rc = sqlite3Fts5IterNextScan(pCsr->pIter); | 477 rc = sqlite3Fts5IterNextScan(pCsr->pIter); |
434 } | 478 } |
435 | 479 |
436 if( rc==SQLITE_OK ){ | 480 if( rc==SQLITE_OK ){ |
437 zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm); | 481 zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm); |
438 if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ){ | 482 if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ){ |
439 break; | 483 break; |
440 } | 484 } |
441 if( sqlite3Fts5IterEof(pCsr->pIter) ) break; | 485 if( sqlite3Fts5IterEof(pCsr->pIter) ) break; |
442 } | 486 } |
443 } | 487 } |
444 } | 488 } |
445 } | 489 } |
446 | 490 |
447 if( pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){ | 491 if( rc==SQLITE_OK && pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){ |
448 while( pCsr->aCnt[pCsr->iCol]==0 ) pCsr->iCol++; | 492 while( pCsr->aDoc[pCsr->iCol]==0 ) pCsr->iCol++; |
449 assert( pCsr->iCol<pCsr->pConfig->nCol ); | 493 assert( pCsr->iCol<pCsr->pConfig->nCol ); |
450 } | 494 } |
451 return rc; | 495 return rc; |
452 } | 496 } |
453 | 497 |
454 /* | 498 /* |
455 ** This is the xFilter implementation for the virtual table. | 499 ** This is the xFilter implementation for the virtual table. |
456 */ | 500 */ |
457 static int fts5VocabFilterMethod( | 501 static int fts5VocabFilterMethod( |
458 sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ | 502 sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ |
459 int idxNum, /* Strategy index */ | 503 int idxNum, /* Strategy index */ |
460 const char *idxStr, /* Unused */ | 504 const char *zUnused, /* Unused */ |
461 int nVal, /* Number of elements in apVal */ | 505 int nUnused, /* Number of elements in apVal */ |
462 sqlite3_value **apVal /* Arguments for the indexing scheme */ | 506 sqlite3_value **apVal /* Arguments for the indexing scheme */ |
463 ){ | 507 ){ |
464 Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; | 508 Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; |
465 int rc = SQLITE_OK; | 509 int rc = SQLITE_OK; |
466 | 510 |
467 int iVal = 0; | 511 int iVal = 0; |
468 int f = FTS5INDEX_QUERY_SCAN; | 512 int f = FTS5INDEX_QUERY_SCAN; |
469 const char *zTerm = 0; | 513 const char *zTerm = 0; |
470 int nTerm = 0; | 514 int nTerm = 0; |
471 | 515 |
472 sqlite3_value *pEq = 0; | 516 sqlite3_value *pEq = 0; |
473 sqlite3_value *pGe = 0; | 517 sqlite3_value *pGe = 0; |
474 sqlite3_value *pLe = 0; | 518 sqlite3_value *pLe = 0; |
475 | 519 |
| 520 UNUSED_PARAM2(zUnused, nUnused); |
| 521 |
476 fts5VocabResetCursor(pCsr); | 522 fts5VocabResetCursor(pCsr); |
477 if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++]; | 523 if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++]; |
478 if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++]; | 524 if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++]; |
479 if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++]; | 525 if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++]; |
480 | 526 |
481 if( pEq ){ | 527 if( pEq ){ |
482 zTerm = (const char *)sqlite3_value_text(pEq); | 528 zTerm = (const char *)sqlite3_value_text(pEq); |
483 nTerm = sqlite3_value_bytes(pEq); | 529 nTerm = sqlite3_value_bytes(pEq); |
484 f = 0; | 530 f = 0; |
485 }else{ | 531 }else{ |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; | 564 Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; |
519 return pCsr->bEof; | 565 return pCsr->bEof; |
520 } | 566 } |
521 | 567 |
522 static int fts5VocabColumnMethod( | 568 static int fts5VocabColumnMethod( |
523 sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ | 569 sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ |
524 sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ | 570 sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ |
525 int iCol /* Index of column to read value from */ | 571 int iCol /* Index of column to read value from */ |
526 ){ | 572 ){ |
527 Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; | 573 Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; |
| 574 int eDetail = pCsr->pConfig->eDetail; |
| 575 int eType = ((Fts5VocabTable*)(pCursor->pVtab))->eType; |
| 576 i64 iVal = 0; |
528 | 577 |
529 if( iCol==0 ){ | 578 if( iCol==0 ){ |
530 sqlite3_result_text( | 579 sqlite3_result_text( |
531 pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT | 580 pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT |
532 ); | 581 ); |
533 } | 582 }else if( eType==FTS5_VOCAB_COL ){ |
534 else if( ((Fts5VocabTable*)(pCursor->pVtab))->eType==FTS5_VOCAB_COL ){ | |
535 assert( iCol==1 || iCol==2 || iCol==3 ); | 583 assert( iCol==1 || iCol==2 || iCol==3 ); |
536 if( iCol==1 ){ | 584 if( iCol==1 ){ |
537 const char *z = pCsr->pConfig->azCol[pCsr->iCol]; | 585 if( eDetail!=FTS5_DETAIL_NONE ){ |
538 sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC); | 586 const char *z = pCsr->pConfig->azCol[pCsr->iCol]; |
| 587 sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC); |
| 588 } |
539 }else if( iCol==2 ){ | 589 }else if( iCol==2 ){ |
540 sqlite3_result_int64(pCtx, pCsr->aDoc[pCsr->iCol]); | 590 iVal = pCsr->aDoc[pCsr->iCol]; |
541 }else{ | 591 }else{ |
542 sqlite3_result_int64(pCtx, pCsr->aCnt[pCsr->iCol]); | 592 iVal = pCsr->aCnt[pCsr->iCol]; |
543 } | 593 } |
544 }else{ | 594 }else{ |
545 assert( iCol==1 || iCol==2 ); | 595 assert( iCol==1 || iCol==2 ); |
546 if( iCol==1 ){ | 596 if( iCol==1 ){ |
547 sqlite3_result_int64(pCtx, pCsr->aDoc[0]); | 597 iVal = pCsr->aDoc[0]; |
548 }else{ | 598 }else{ |
549 sqlite3_result_int64(pCtx, pCsr->aCnt[0]); | 599 iVal = pCsr->aCnt[0]; |
550 } | 600 } |
551 } | 601 } |
| 602 |
| 603 if( iVal>0 ) sqlite3_result_int64(pCtx, iVal); |
552 return SQLITE_OK; | 604 return SQLITE_OK; |
553 } | 605 } |
554 | 606 |
555 /* | 607 /* |
556 ** This is the xRowid method. The SQLite core calls this routine to | 608 ** This is the xRowid method. The SQLite core calls this routine to |
557 ** retrieve the rowid for the current row of the result set. The | 609 ** retrieve the rowid for the current row of the result set. The |
558 ** rowid should be written to *pRowid. | 610 ** rowid should be written to *pRowid. |
559 */ | 611 */ |
560 static int fts5VocabRowidMethod( | 612 static int fts5VocabRowidMethod( |
561 sqlite3_vtab_cursor *pCursor, | 613 sqlite3_vtab_cursor *pCursor, |
(...skipping 29 matching lines...) Expand all Loading... |
591 /* xSavepoint */ 0, | 643 /* xSavepoint */ 0, |
592 /* xRelease */ 0, | 644 /* xRelease */ 0, |
593 /* xRollbackTo */ 0, | 645 /* xRollbackTo */ 0, |
594 }; | 646 }; |
595 void *p = (void*)pGlobal; | 647 void *p = (void*)pGlobal; |
596 | 648 |
597 return sqlite3_create_module_v2(db, "fts5vocab", &fts5Vocab, p, 0); | 649 return sqlite3_create_module_v2(db, "fts5vocab", &fts5Vocab, p, 0); |
598 } | 650 } |
599 | 651 |
600 | 652 |
OLD | NEW |