Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch vs2010 Excluding Merge-Ins
This is equivalent to a diff from 7f9e634bf5 to 8a92ed133d
2011-01-04
| ||
21:55 | Merge the VS2010 updates into trunk. check-in: b6e6cd73f6 user: drh tags: trunk | |
20:46 | Update internal SQLite engine to 3.7.4. Update SDS version to 1.0.67.0. Closed-Leaf check-in: 8a92ed133d user: shaneh tags: vs2010 | |
2010-12-20
| ||
18:34 | Another missing project file. check-in: eb30ee2240 user: shaneh tags: vs2010 | |
2010-12-16
| ||
17:49 | Changes to get base portions compiling under Visual Studio 2010. Still much to be done. Need to sort out packaging, installation, wince, etc. check-in: 644aeca13c user: shaneh tags: vs2010 | |
2010-11-24
| ||
14:29 | Remove a duplicate DLL whose name differs only in case. check-in: 7f9e634bf5 user: drh tags: trunk | |
2010-08-15
| ||
22:10 | Fix guid type Closed-Leaf check-in: 555d0d530d user: rmsimpson tags: sourceforge | |
Changes to Doc/Extra/dbfactorysupport.html.
︙ | |||
93 94 95 96 97 98 99 | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | - + | <configuration> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite"/> <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, |
︙ |
Changes to Doc/Extra/version.html.
︙ | |||
51 52 53 54 55 56 57 58 59 60 61 62 63 64 | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | + + + + + + + + + + + + + | </td> </tr> </table> </div> <div id="mainSection"> <div id="mainBody"> <h1 class="heading">Version History</h1> <p><b>1.0.67.0 - January 3, 2011</b></p> <ul> <li>Code merge with SQLite 3.7.4</li> <li>Continuing work on supporting Visual Studio 2010</li> </ul> <p><b>1.0.66.1 - August 1, 2010</b></p> <ul> <li>Code merge with SQLite 3.7.0.1</li> <li>Re-enabled VS2005 designer support, broken in previous versions during the 2008 transition</li> <li>Implemented new forms of Take/Skip in the EF framework courtesy jlsantiago</li> <li>Added "Foreign Keys" to the connection string parameters</li> <li>Added the Truncate option to the Journal Modes enumeration</li> </ul> <p><b>1.0.66.0 - April 18, 2010</b></p> <ul> <li>Code merge with SQLite 3.6.23.1</li> <li>Fixed a bug in the installer that accidentally modified the machine.config on .NET versions prior to 2.0, invaliding the config file.</li> <li>Fixed INTERSECT and EXCEPT union query generation in EF</li> <li>Fixed an out of memory error in the trigger designer in cases where a WHEN clause is used in the trigger</li> </ul> |
︙ |
Changes to SQLite.Designer/AssemblyInfo.cs.
1 2 3 4 5 6 7 8 9 10 11 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | - + | using System; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.ConstrainedExecution; using System.Resources; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("SQLite.Designer")] |
︙ | |||
30 31 32 33 34 35 36 | 30 31 32 33 34 35 36 37 38 39 40 41 | - - + + | // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: |
Changes to SQLite.Designer/SQLite.Designer.csproj.
|
Changes to SQLite.Designer/SQLite.Designer.sln.
1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | - - + + - - - + + + + - - + + + + - - + + - - - - + + + + |
|
Changes to SQLite.Designer/SQLiteDataViewSupport.cs.
︙ | |||
27 28 29 30 31 32 33 | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | - - - - + + + + | private static string GetVSVersion() { switch (System.Diagnostics.FileVersionInfo.GetVersionInfo(Environment.GetCommandLineArgs()[0]).FileMajorPart) { case 8: return "2005"; |
Changes to SQLite.Designer/VSPackage.Designer.cs.
1 2 3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | - + - + | //------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. |
︙ | |||
100 101 102 103 104 105 106 | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | - + + + + + | internal static string ReEncrypt { get { return ResourceManager.GetString("ReEncrypt", resourceCulture); } } /// <summary> |
Changes to SQLite.Interop/FTS2/fts2.c.
1 2 3 4 5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | + - + | /* fts2 has a design flaw which can lead to database corruption (see ** below). It is recommended not to use it any longer, instead use ** fts3 (or higher). If you believe that your use of fts2 is safe, ** add -DSQLITE_ENABLE_BROKEN_FTS2=1 to your CFLAGS. */ #if (!defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)) \ |
︙ | |||
269 270 271 272 273 274 275 | 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | - + | ** ** This appears to have only a moderate impact on queries for very ** frequent terms (which are somewhat dominated by segment merge ** costs), and infrequent and non-existent terms still seem to be fast ** even with many segments. ** ** TODO(shess) That said, it would be nice to have a better query-side |
︙ | |||
301 302 303 304 305 306 307 | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | - - | # define SQLITE_CORE 1 #endif #include <assert.h> #include <stdlib.h> #include <stdio.h> #include <string.h> |
︙ | |||
340 341 342 343 344 345 346 | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 | - + - + - + | */ /* TODO(shess) The snippet-generation code should be using the ** tokenizer-generated tokens rather than doing its own local ** tokenization. */ /* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */ static int safe_isspace(char c){ |
︙ | |||
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 | 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 | + - + - + + + + + + - + | /* DataBuffer is used to collect data into a buffer in piecemeal ** fashion. It implements the usual distinction between amount of ** data currently stored (nData) and buffer capacity (nCapacity). ** ** dataBufferInit - create a buffer with given initial capacity. ** dataBufferReset - forget buffer's data, retaining capacity. ** dataBufferDestroy - free buffer's data. ** dataBufferSwap - swap contents of two buffers. ** dataBufferExpand - expand capacity without adding data. ** dataBufferAppend - append data. ** dataBufferAppend2 - append two pieces of data at once. ** dataBufferReplace - replace buffer's data. */ typedef struct DataBuffer { char *pData; /* Pointer to malloc'ed buffer. */ int nCapacity; /* Size of pData buffer. */ int nData; /* End of data loaded into pData. */ } DataBuffer; static void dataBufferInit(DataBuffer *pBuffer, int nCapacity){ assert( nCapacity>=0 ); pBuffer->nData = 0; pBuffer->nCapacity = nCapacity; |
︙ | |||
689 690 691 692 693 694 695 | 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 | - + | } static void dlrDestroy(DLReader *pReader){ SCRAMBLE(pReader); } #ifndef NDEBUG /* Verify that the doclist can be validly decoded. Also returns the |
︙ | |||
1052 1053 1054 1055 1056 1057 1058 | 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 | - + | DLWriter dlw; PLWriter plw; } DLCollector; /* TODO(shess) This could also be done by calling plwTerminate() and ** dataBufferAppend(). I tried that, expecting nominal performance ** differences, but it seemed to pretty reliably be worth 1% to code |
︙ | |||
1077 1078 1079 1080 1081 1082 1083 | 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 | - + - + | } static void dlcAddPos(DLCollector *pCollector, int iColumn, int iPos, int iStartOffset, int iEndOffset){ plwAdd(&pCollector->plw, iColumn, iPos, iStartOffset, iEndOffset); } static DLCollector *dlcNew(sqlite_int64 iDocid, DocListType iType){ |
︙ | |||
1347 1348 1349 1350 1351 1352 1353 | 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 | - + | const char *pRight, int nRight, DataBuffer *pOut /* Write the combined doclist here */ ){ DLReader left, right; DLWriter writer; if( nLeft==0 ){ |
︙ | |||
1528 1529 1530 1531 1532 1533 1534 | 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 | - + | const char *pRight, int nRight, DataBuffer *pOut /* Write the combined doclist here */ ){ DLReader left, right; DLWriter writer; if( nLeft==0 ){ |
︙ | |||
1603 1604 1605 1606 1607 1608 1609 | 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 | - + - + | dlrDestroy(&left); dlrDestroy(&right); dlwDestroy(&writer); } static char *string_dup_n(const char *s, int n){ |
︙ | |||
1636 1637 1638 1639 1640 1641 1642 | 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 | - + | /* first compute length needed */ for(p = zFormat ; *p ; ++p){ len += (*p=='%' ? nFullTableName : 1); } len += 1; /* for null terminator */ |
︙ | |||
1659 1660 1661 1662 1663 1664 1665 | 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 | - + - + | static int sql_exec(sqlite3 *db, const char *zDb, const char *zName, const char *zFormat){ char *zCommand = string_format(zFormat, zDb, zName); int rc; TRACE(("FTS2 sql: %s\n", zCommand)); rc = sqlite3_exec(db, zCommand, NULL, 0, NULL); |
︙ | |||
1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 | 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 | + + - + + + + + + - + + + + + + + + + - + + + | } QueryType; typedef enum fulltext_statement { CONTENT_INSERT_STMT, CONTENT_SELECT_STMT, CONTENT_UPDATE_STMT, CONTENT_DELETE_STMT, CONTENT_EXISTS_STMT, BLOCK_INSERT_STMT, BLOCK_SELECT_STMT, BLOCK_DELETE_STMT, BLOCK_DELETE_ALL_STMT, SEGDIR_MAX_INDEX_STMT, SEGDIR_SET_STMT, |
︙ | |||
1933 1934 1935 1936 1937 1938 1939 | 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 | - + - + + - - + + + + | case CONTENT_UPDATE_STMT: zStmt = contentUpdateStatement(v); break; default: zStmt = fulltext_zStatement[iStmt]; } rc = sql_prepare(v->db, v->zDb, v->zName, &v->pFulltextStatements[iStmt], zStmt); |
︙ | |||
2018 2019 2020 2021 2022 2023 2024 | 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 | - + - + | return sql_single_step(s); } static void freeStringArray(int nString, const char **pString){ int i; for (i=0 ; i < nString ; ++i) { |
︙ | |||
2047 2048 2049 2050 2051 2052 2053 | 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 | - + | rc = sqlite3_bind_int64(s, 1, iRow); if( rc!=SQLITE_OK ) return rc; rc = sqlite3_step(s); if( rc!=SQLITE_ROW ) return rc; |
︙ | |||
2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 | 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 | + + + + + + + + + + + + + + + + + + + | if( rc!=SQLITE_OK ) return rc; rc = sqlite3_bind_int64(s, 1, iRow); if( rc!=SQLITE_OK ) return rc; return sql_single_step(s); } /* Returns SQLITE_ROW if any rows exist in %_content, SQLITE_DONE if ** no rows exist, and any error in case of failure. */ static int content_exists(fulltext_vtab *v){ sqlite3_stmt *s; int rc = sql_get_statement(v, CONTENT_EXISTS_STMT, &s); if( rc!=SQLITE_OK ) return rc; rc = sqlite3_step(s); if( rc!=SQLITE_ROW ) return rc; /* We expect only one row. We must execute another sqlite3_step() * to complete the iteration; otherwise the table will remain locked. */ rc = sqlite3_step(s); if( rc==SQLITE_DONE ) return SQLITE_ROW; if( rc==SQLITE_ROW ) return SQLITE_ERROR; return rc; } /* insert into %_segments values ([pData]) ** returns assigned rowid in *piBlockid */ static int block_insert(fulltext_vtab *v, const char *pData, int nData, sqlite_int64 *piBlockid){ sqlite3_stmt *s; |
︙ | |||
2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 | 2296 2297 2298 2299 2300 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 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | if( rc!=SQLITE_OK ) return rc; rc = sqlite3_bind_int64(s, 1, iLevel); if( rc!=SQLITE_OK ) return rc; return sql_single_step(s); } /* Delete entire fts index, SQLITE_OK on success, relevant error on ** failure. */ static int segdir_delete_all(fulltext_vtab *v){ sqlite3_stmt *s; int rc = sql_get_statement(v, SEGDIR_DELETE_ALL_STMT, &s); if( rc!=SQLITE_OK ) return rc; rc = sql_single_step(s); if( rc!=SQLITE_OK ) return rc; rc = sql_get_statement(v, BLOCK_DELETE_ALL_STMT, &s); if( rc!=SQLITE_OK ) return rc; return sql_single_step(s); } /* Returns SQLITE_OK with *pnSegments set to the number of entries in ** %_segdir and *piMaxLevel set to the highest level which has a ** segment. Otherwise returns the SQLite error which caused failure. */ static int segdir_count(fulltext_vtab *v, int *pnSegments, int *piMaxLevel){ sqlite3_stmt *s; int rc = sql_get_statement(v, SEGDIR_COUNT_STMT, &s); if( rc!=SQLITE_OK ) return rc; rc = sqlite3_step(s); /* TODO(shess): This case should not be possible? Should stronger ** measures be taken if it happens? */ if( rc==SQLITE_DONE ){ *pnSegments = 0; *piMaxLevel = 0; return SQLITE_OK; } if( rc!=SQLITE_ROW ) return rc; *pnSegments = sqlite3_column_int(s, 0); *piMaxLevel = sqlite3_column_int(s, 1); /* We expect only one row. We must execute another sqlite3_step() * to complete the iteration; otherwise the table will remain locked. */ rc = sqlite3_step(s); if( rc==SQLITE_DONE ) return SQLITE_OK; if( rc==SQLITE_ROW ) return SQLITE_ERROR; return rc; } /* TODO(shess) clearPendingTerms() is far down the file because ** writeZeroSegment() is far down the file because LeafWriter is far ** down the file. Consider refactoring the code to move the non-vtab ** code above the vtab code so that we don't need this forward ** reference. */ |
︙ | |||
2289 2290 2291 2292 2293 2294 2295 | 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 | - + - - + + | if( v->pTokenizer!=NULL ){ v->pTokenizer->pModule->xDestroy(v->pTokenizer); v->pTokenizer = NULL; } clearPendingTerms(v); |
︙ | |||
2405 2406 2407 2408 2409 2410 2411 | 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 | - + - + - + | ** Space to hold the returned array is obtained from a single ** malloc and should be freed by passing the return value to free(). ** The individual strings within the token list are all a part of ** the single memory allocation and will all be freed at once. */ static char **tokenizeString(const char *z, int *pnToken){ int nToken = 0; |
︙ | |||
2570 2571 2572 2573 2574 2575 2576 | 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 | - - - + + + | char **azTokenizer; /* Name of tokenizer and its arguments */ } TableSpec; /* ** Reclaim all of the memory used by a TableSpec */ static void clearTableSpec(TableSpec *p) { |
︙ | |||
2607 2608 2609 2610 2611 2612 2613 | 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 | - + | ** The argv[][] array is read-only and transient. We can write to the ** copy in order to modify things and the copy is persistent. */ CLEAR(pSpec); for(i=n=0; i<argc; i++){ n += strlen(argv[i]) + 1; } |
︙ | |||
2652 2653 2654 2655 2656 2657 2658 | 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 | - + | ** converted to "_". The cNN prefix guarantees that all column ** names are unique. ** ** The AAAA suffix is not strictly necessary. It is included ** for the convenience of people who might examine the generated ** %_content table and wonder what the columns are used for. */ |
︙ | |||
2721 2722 2723 2724 2725 2726 2727 | 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 | - + | fulltext_vtab *v = 0; const sqlite3_tokenizer_module *m = NULL; char *schema; char const *zTok; /* Name of tokenizer to use for this fts table */ int nTok; /* Length of zTok, including nul terminator */ |
︙ | |||
2908 2909 2910 2911 2912 2913 2914 | 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 | - - - - - - + + + + + + + + + + - + - + - - - + + + - + | fulltext_vtab_destroy((fulltext_vtab *)pVTab); return SQLITE_OK; } static int fulltextOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ fulltext_cursor *c; |
︙ | |||
3090 3091 3092 3093 3094 3095 3096 | 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 | - - + + | StringBuffer sb; char zBuf[200]; if( p->zOffset ) return; initStringBuffer(&sb); for(i=0; i<p->nMatch; i++){ struct snippetMatch *pMatch = &p->aMatch[i]; zBuf[0] = ' '; |
︙ | |||
3176 3177 3178 3179 3180 3181 3182 | 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 | - + | int nDoc; const char *zDoc; int iStart, iEnd; int tailEllipsis = 0; int iMatch; |
︙ | |||
3278 3279 3280 3281 3282 3283 3284 | 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 | - + | fulltext_cursor *c = (fulltext_cursor *) pCursor; TRACE(("FTS2 Close %p\n", c)); sqlite3_finalize(c->pStmt); queryClear(&c->q); snippetClear(&c->snippet); if( c->result.nData!=0 ) dlrDestroy(&c->reader); dataBufferDestroy(&c->result); |
︙ | |||
3383 3384 3385 3386 3387 3388 3389 | 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 | - + - + | } /* Add a new term pTerm[0..nTerm-1] to the query *q. */ static void queryAdd(Query *q, const char *pTerm, int nTerm){ QueryTerm *t; ++q->nTerms; |
︙ | |||
3675 3676 3677 3678 3679 3680 3681 | 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 | - + + + + + + + + + + + + + + + + + + - - + + - - - - - - + + + + + + + + + | sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ int idxNum, const char *idxStr, /* Which indexing scheme to use */ int argc, sqlite3_value **argv /* Arguments for the indexing scheme */ ){ fulltext_cursor *c = (fulltext_cursor *) pCursor; fulltext_vtab *v = cursor_vtab(c); int rc; |
︙ | |||
3781 3782 3783 3784 3785 3786 3787 | 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 | - - - - + + + + - - + + + - - + + | int iStartOffset, iEndOffset, iPosition; int rc; rc = pTokenizer->pModule->xOpen(pTokenizer, zText, -1, &pCursor); if( rc!=SQLITE_OK ) return rc; pCursor->pTokenizer = pTokenizer; |
︙ | |||
3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 | 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 | + | /* TODO(shess) Check return? Should this be able to cause errors at ** this point? Actually, same question about sqlite3_finalize(), ** though one could argue that failure there means that the data is ** not durable. *ponder* */ pTokenizer->pModule->xClose(pCursor); if( SQLITE_DONE == rc ) return SQLITE_OK; return rc; } /* Add doclists for all terms in [pValues] to pendingTerms table. */ static int insertTerms(fulltext_vtab *v, sqlite_int64 iRowid, sqlite3_value **pValues){ int i; |
︙ | |||
3954 3955 3956 3957 3958 3959 3960 | 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 | - + + + - - + + - - - - - + + + + + | DataBuffer term; /* Leftmost term in block's subtree. */ DataBuffer data; /* Accumulated data for the block. */ struct InteriorBlock *next; } InteriorBlock; static InteriorBlock *interiorBlockNew(int iHeight, sqlite_int64 iChildBlock, const char *pTerm, int nTerm){ |
︙ | |||
4130 4131 4132 4133 4134 4135 4136 | 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 | - + - + | InteriorBlock *block = pWriter->first; while( block!=NULL ){ InteriorBlock *b = block; block = block->next; dataBufferDestroy(&b->term); dataBufferDestroy(&b->data); |
︙ | |||
4168 4169 4170 4171 4172 4173 4174 | 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 | - + | ** interior node. */ ASSERT_VALID_INTERIOR_BLOCK(block); rc = block_insert(v, block->data.pData, block->data.nData, &iBlockid); if( rc!=SQLITE_OK ) return rc; *piEndBlockid = iBlockid; |
︙ | |||
4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 | 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 | + + + + + + | ** this case. Probably a brittle assumption. */ static int leavesReaderReset(LeavesReader *pReader){ return sqlite3_reset(pReader->pStmt); } static void leavesReaderDestroy(LeavesReader *pReader){ /* If idx is -1, that means we're using a non-cached statement ** handle in the optimize() case, so we need to release it. */ if( pReader->pStmt!=NULL && pReader->idx==-1 ){ sqlite3_finalize(pReader->pStmt); } leafReaderDestroy(&pReader->leafReader); dataBufferDestroy(&pReader->rootData); SCRAMBLE(pReader); } /* Initialize pReader with the given root data (if iStartBlockid==0 ** the leaf data was entirely contained in the root), or from the |
︙ | |||
5056 5057 5058 5059 5060 5061 5062 | 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 | - + | /* Initializes pReaders with the segments from level iLevel, returning ** the number of segments in *piReaders. Leaves pReaders in sorted ** order. */ static int leavesReadersInit(fulltext_vtab *v, int iLevel, LeavesReader *pReaders, int *piReaders){ sqlite3_stmt *s; |
︙ | |||
5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 | 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | err: for(i=0; i<MERGE_COUNT; i++){ leavesReaderDestroy(&lrs[i]); } leafWriterDestroy(&writer); return rc; } /* Accumulate the union of *acc and *pData into *acc. */ static void docListAccumulateUnion(DataBuffer *acc, const char *pData, int nData) { DataBuffer tmp = *acc; dataBufferInit(acc, tmp.nData+nData); docListUnion(tmp.pData, tmp.nData, pData, nData, acc); dataBufferDestroy(&tmp); } /* TODO(shess) It might be interesting to explore different merge ** strategies, here. For instance, since this is a sorted merge, we ** could easily merge many doclists in parallel. With some ** comprehension of the storage format, we could merge all of the ** doclists within a leaf node directly from the leaf node's storage. ** It may be worthwhile to merge smaller doclists before larger ** doclists, since they can be traversed more quickly - but the ** results may have less overlap, making them more expensive in a ** different way. */ /* Scan pReader for pTerm/nTerm, and merge the term's doclist over ** *out (any doclists with duplicate docids overwrite those in *out). ** Internal function for loadSegmentLeaf(). */ static int loadSegmentLeavesInt(fulltext_vtab *v, LeavesReader *pReader, const char *pTerm, int nTerm, int isPrefix, DataBuffer *out){ /* doclist data is accumulated into pBuffers similar to how one does ** increment in binary arithmetic. If index 0 is empty, the data is ** stored there. If there is data there, it is merged and the ** results carried into position 1, with further merge-and-carry ** until an empty position is found. */ DataBuffer *pBuffers = NULL; int nBuffers = 0, nMaxBuffers = 0, rc; assert( nTerm>0 ); |
︙ | |||
5298 5299 5300 5301 5302 5303 5304 | 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 | - + | ** interior node terms logically come between the blocks, so there is ** one more blockid than there are terms (that block contains terms >= ** the last interior-node term). */ /* TODO(shess) The calling code may already know that the end child is ** not worth calculating, because the end may be in a later sibling ** node. Consider whether breaking symmetry is worthwhile. I suspect |
︙ | |||
5497 5498 5499 5500 5501 5502 5503 | 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 | - - + + | dataBufferInit(&doclist, 0); /* Traverse the segments from oldest to newest so that newer doclist ** elements for given docids overwrite older elements. */ while( (rc = sqlite3_step(s))==SQLITE_ROW ){ |
︙ | |||
5558 5559 5560 5561 5562 5563 5564 | 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 | - + | DataBuffer dl; /* Determine the next index at level 0, merging as necessary. */ rc = segdirNextIndex(v, 0, &idx); if( rc!=SQLITE_OK ) return rc; n = fts2HashCount(pTerms); |
︙ | |||
5589 5590 5591 5592 5593 5594 5595 | 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 | - + | pData[i].pTerm, pData[i].nTerm, dl.pData, dl.nData); if( rc!=SQLITE_OK ) goto err; } rc = leafWriterFinalize(v, &writer); err: dataBufferDestroy(&dl); |
︙ | |||
5641 5642 5643 5644 5645 5646 5647 | 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 | - + + + + + + + + + + + + + + + + + + | fts2HashInit(&v->pendingTerms, FTS2_HASH_STRING, 1); v->nPendingData = 0; } v->iPrevDocid = iDocid; return SQLITE_OK; } |
︙ | |||
5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 | 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | snippetOffsetText(&pCursor->snippet); sqlite3_result_text(pContext, pCursor->snippet.zOffset, pCursor->snippet.nOffset, SQLITE_STATIC); } } /* OptLeavesReader is nearly identical to LeavesReader, except that ** where LeavesReader is geared towards the merging of complete ** segment levels (with exactly MERGE_COUNT segments), OptLeavesReader ** is geared towards implementation of the optimize() function, and ** can merge all segments simultaneously. This version may be ** somewhat less efficient than LeavesReader because it merges into an ** accumulator rather than doing an N-way merge, but since segment ** size grows exponentially (so segment count logrithmically) this is ** probably not an immediate problem. */ /* TODO(shess): Prove that assertion, or extend the merge code to ** merge tree fashion (like the prefix-searching code does). */ /* TODO(shess): OptLeavesReader and LeavesReader could probably be ** merged with little or no loss of performance for LeavesReader. The ** merged code would need to handle >MERGE_COUNT segments, and would ** also need to be able to optionally optimize away deletes. */ typedef struct OptLeavesReader { /* Segment number, to order readers by age. */ int segment; LeavesReader reader; } OptLeavesReader; static int optLeavesReaderAtEnd(OptLeavesReader *pReader){ return leavesReaderAtEnd(&pReader->reader); } static int optLeavesReaderTermBytes(OptLeavesReader *pReader){ return leavesReaderTermBytes(&pReader->reader); } static const char *optLeavesReaderData(OptLeavesReader *pReader){ return leavesReaderData(&pReader->reader); } static int optLeavesReaderDataBytes(OptLeavesReader *pReader){ return leavesReaderDataBytes(&pReader->reader); } static const char *optLeavesReaderTerm(OptLeavesReader *pReader){ return leavesReaderTerm(&pReader->reader); } static int optLeavesReaderStep(fulltext_vtab *v, OptLeavesReader *pReader){ return leavesReaderStep(v, &pReader->reader); } static int optLeavesReaderTermCmp(OptLeavesReader *lr1, OptLeavesReader *lr2){ return leavesReaderTermCmp(&lr1->reader, &lr2->reader); } /* Order by term ascending, segment ascending (oldest to newest), with ** exhausted readers to the end. */ static int optLeavesReaderCmp(OptLeavesReader *lr1, OptLeavesReader *lr2){ int c = optLeavesReaderTermCmp(lr1, lr2); if( c!=0 ) return c; return lr1->segment-lr2->segment; } /* Bubble pLr[0] to appropriate place in pLr[1..nLr-1]. Assumes that ** pLr[1..nLr-1] is already sorted. */ static void optLeavesReaderReorder(OptLeavesReader *pLr, int nLr){ while( nLr>1 && optLeavesReaderCmp(pLr, pLr+1)>0 ){ OptLeavesReader tmp = pLr[0]; pLr[0] = pLr[1]; pLr[1] = tmp; nLr--; pLr++; } } /* optimize() helper function. Put the readers in order and iterate ** through them, merging doclists for matching terms into pWriter. ** Returns SQLITE_OK on success, or the SQLite error code which ** prevented success. */ static int optimizeInternal(fulltext_vtab *v, OptLeavesReader *readers, int nReaders, LeafWriter *pWriter){ int i, rc = SQLITE_OK; DataBuffer doclist, merged, tmp; /* Order the readers. */ i = nReaders; while( i-- > 0 ){ optLeavesReaderReorder(&readers[i], nReaders-i); } dataBufferInit(&doclist, LEAF_MAX); dataBufferInit(&merged, LEAF_MAX); /* Exhausted readers bubble to the end, so when the first reader is ** at eof, all are at eof. */ while( !optLeavesReaderAtEnd(&readers[0]) ){ /* Figure out how many readers share the next term. */ for(i=1; i<nReaders && !optLeavesReaderAtEnd(&readers[i]); i++){ if( 0!=optLeavesReaderTermCmp(&readers[0], &readers[i]) ) break; } /* Special-case for no merge. */ if( i==1 ){ /* Trim deletions from the doclist. */ dataBufferReset(&merged); docListTrim(DL_DEFAULT, optLeavesReaderData(&readers[0]), optLeavesReaderDataBytes(&readers[0]), -1, DL_DEFAULT, &merged); }else{ DLReader dlReaders[MERGE_COUNT]; int iReader, nReaders; /* Prime the pipeline with the first reader's doclist. After ** one pass index 0 will reference the accumulated doclist. */ dlrInit(&dlReaders[0], DL_DEFAULT, optLeavesReaderData(&readers[0]), optLeavesReaderDataBytes(&readers[0])); iReader = 1; assert( iReader<i ); /* Must execute the loop at least once. */ while( iReader<i ){ /* Merge 16 inputs per pass. */ for( nReaders=1; iReader<i && nReaders<MERGE_COUNT; iReader++, nReaders++ ){ dlrInit(&dlReaders[nReaders], DL_DEFAULT, optLeavesReaderData(&readers[iReader]), optLeavesReaderDataBytes(&readers[iReader])); } /* Merge doclists and swap result into accumulator. */ dataBufferReset(&merged); docListMerge(&merged, dlReaders, nReaders); tmp = merged; merged = doclist; doclist = tmp; while( nReaders-- > 0 ){ dlrDestroy(&dlReaders[nReaders]); } /* Accumulated doclist to reader 0 for next pass. */ dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData); } /* Destroy reader that was left in the pipeline. */ dlrDestroy(&dlReaders[0]); /* Trim deletions from the doclist. */ dataBufferReset(&merged); docListTrim(DL_DEFAULT, doclist.pData, doclist.nData, -1, DL_DEFAULT, &merged); } /* Only pass doclists with hits (skip if all hits deleted). */ if( merged.nData>0 ){ rc = leafWriterStep(v, pWriter, optLeavesReaderTerm(&readers[0]), optLeavesReaderTermBytes(&readers[0]), merged.pData, merged.nData); if( rc!=SQLITE_OK ) goto err; } /* Step merged readers to next term and reorder. */ while( i-- > 0 ){ rc = optLeavesReaderStep(v, &readers[i]); if( rc!=SQLITE_OK ) goto err; optLeavesReaderReorder(&readers[i], nReaders-i); } } err: dataBufferDestroy(&doclist); dataBufferDestroy(&merged); return rc; } /* Implement optimize() function for FTS3. optimize(t) merges all ** segments in the fts index into a single segment. 't' is the magic ** table-named column. */ static void optimizeFunc(sqlite3_context *pContext, int argc, sqlite3_value **argv){ fulltext_cursor *pCursor; if( argc>1 ){ sqlite3_result_error(pContext, "excess arguments to optimize()",-1); }else if( sqlite3_value_type(argv[0])!=SQLITE_BLOB || sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){ sqlite3_result_error(pContext, "illegal first argument to optimize",-1); }else{ fulltext_vtab *v; int i, rc, iMaxLevel; OptLeavesReader *readers; int nReaders; LeafWriter writer; sqlite3_stmt *s; memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor)); v = cursor_vtab(pCursor); /* Flush any buffered updates before optimizing. */ rc = flushPendingTerms(v); if( rc!=SQLITE_OK ) goto err; rc = segdir_count(v, &nReaders, &iMaxLevel); if( rc!=SQLITE_OK ) goto err; if( nReaders==0 || nReaders==1 ){ sqlite3_result_text(pContext, "Index already optimal", -1, SQLITE_STATIC); return; } rc = sql_get_statement(v, SEGDIR_SELECT_ALL_STMT, &s); if( rc!=SQLITE_OK ) goto err; readers = sqlite3_malloc(nReaders*sizeof(readers[0])); if( readers==NULL ) goto err; /* Note that there will already be a segment at this position ** until we call segdir_delete() on iMaxLevel. */ leafWriterInit(iMaxLevel, 0, &writer); i = 0; while( (rc = sqlite3_step(s))==SQLITE_ROW ){ sqlite_int64 iStart = sqlite3_column_int64(s, 0); sqlite_int64 iEnd = sqlite3_column_int64(s, 1); const char *pRootData = sqlite3_column_blob(s, 2); int nRootData = sqlite3_column_bytes(s, 2); assert( i<nReaders ); rc = leavesReaderInit(v, -1, iStart, iEnd, pRootData, nRootData, &readers[i].reader); if( rc!=SQLITE_OK ) break; readers[i].segment = i; i++; } /* If we managed to successfully read them all, optimize them. */ if( rc==SQLITE_DONE ){ assert( i==nReaders ); rc = optimizeInternal(v, readers, nReaders, &writer); } while( i-- > 0 ){ leavesReaderDestroy(&readers[i].reader); } sqlite3_free(readers); /* If we've successfully gotten to here, delete the old segments ** and flush the interior structure of the new segment. */ if( rc==SQLITE_OK ){ for( i=0; i<=iMaxLevel; i++ ){ rc = segdir_delete(v, i); if( rc!=SQLITE_OK ) break; } if( rc==SQLITE_OK ) rc = leafWriterFinalize(v, &writer); } leafWriterDestroy(&writer); if( rc!=SQLITE_OK ) goto err; sqlite3_result_text(pContext, "Index optimized", -1, SQLITE_STATIC); return; /* TODO(shess): Error-handling needs to be improved along the ** lines of the dump_ functions. */ err: { char buf[512]; sqlite3_snprintf(sizeof(buf), buf, "Error in optimize: %s", sqlite3_errmsg(sqlite3_context_db_handle(pContext))); sqlite3_result_error(pContext, buf, -1); } } } #ifdef SQLITE_TEST /* Generate an error of the form "<prefix>: <msg>". If msg is NULL, ** pull the error from the context's db handle. */ static void generateError(sqlite3_context *pContext, const char *prefix, const char *msg){ char buf[512]; if( msg==NULL ) msg = sqlite3_errmsg(sqlite3_context_db_handle(pContext)); sqlite3_snprintf(sizeof(buf), buf, "%s: %s", prefix, msg); sqlite3_result_error(pContext, buf, -1); } /* Helper function to collect the set of terms in the segment into ** pTerms. The segment is defined by the leaf nodes between ** iStartBlockid and iEndBlockid, inclusive, or by the contents of ** pRootData if iStartBlockid is 0 (in which case the entire segment ** fit in a leaf). */ static int collectSegmentTerms(fulltext_vtab *v, sqlite3_stmt *s, fts2Hash *pTerms){ const sqlite_int64 iStartBlockid = sqlite3_column_int64(s, 0); const sqlite_int64 iEndBlockid = sqlite3_column_int64(s, 1); const char *pRootData = sqlite3_column_blob(s, 2); const int nRootData = sqlite3_column_bytes(s, 2); LeavesReader reader; int rc = leavesReaderInit(v, 0, iStartBlockid, iEndBlockid, pRootData, nRootData, &reader); if( rc!=SQLITE_OK ) return rc; while( rc==SQLITE_OK && !leavesReaderAtEnd(&reader) ){ const char *pTerm = leavesReaderTerm(&reader); const int nTerm = leavesReaderTermBytes(&reader); void *oldValue = sqlite3Fts2HashFind(pTerms, pTerm, nTerm); void *newValue = (void *)((char *)oldValue+1); /* From the comment before sqlite3Fts2HashInsert in fts2_hash.c, ** the data value passed is returned in case of malloc failure. */ if( newValue==sqlite3Fts2HashInsert(pTerms, pTerm, nTerm, newValue) ){ rc = SQLITE_NOMEM; }else{ rc = leavesReaderStep(v, &reader); } } leavesReaderDestroy(&reader); return rc; } /* Helper function to build the result string for dump_terms(). */ static int generateTermsResult(sqlite3_context *pContext, fts2Hash *pTerms){ int iTerm, nTerms, nResultBytes, iByte; char *result; TermData *pData; fts2HashElem *e; /* Iterate pTerms to generate an array of terms in pData for ** sorting. */ nTerms = fts2HashCount(pTerms); assert( nTerms>0 ); pData = sqlite3_malloc(nTerms*sizeof(TermData)); if( pData==NULL ) return SQLITE_NOMEM; nResultBytes = 0; for(iTerm = 0, e = fts2HashFirst(pTerms); e; iTerm++, e = fts2HashNext(e)){ nResultBytes += fts2HashKeysize(e)+1; /* Term plus trailing space */ assert( iTerm<nTerms ); pData[iTerm].pTerm = fts2HashKey(e); pData[iTerm].nTerm = fts2HashKeysize(e); pData[iTerm].pCollector = fts2HashData(e); /* unused */ } assert( iTerm==nTerms ); assert( nResultBytes>0 ); /* nTerms>0, nResultsBytes must be, too. */ result = sqlite3_malloc(nResultBytes); if( result==NULL ){ sqlite3_free(pData); return SQLITE_NOMEM; } if( nTerms>1 ) qsort(pData, nTerms, sizeof(*pData), termDataCmp); /* Read the terms in order to build the result. */ iByte = 0; for(iTerm=0; iTerm<nTerms; ++iTerm){ memcpy(result+iByte, pData[iTerm].pTerm, pData[iTerm].nTerm); iByte += pData[iTerm].nTerm; result[iByte++] = ' '; } assert( iByte==nResultBytes ); assert( result[nResultBytes-1]==' ' ); result[nResultBytes-1] = '\0'; /* Passes away ownership of result. */ sqlite3_result_text(pContext, result, nResultBytes-1, sqlite3_free); sqlite3_free(pData); return SQLITE_OK; } /* Implements dump_terms() for use in inspecting the fts2 index from ** tests. TEXT result containing the ordered list of terms joined by ** spaces. dump_terms(t, level, idx) dumps the terms for the segment ** specified by level, idx (in %_segdir), while dump_terms(t) dumps ** all terms in the index. In both cases t is the fts table's magic ** table-named column. */ static void dumpTermsFunc( sqlite3_context *pContext, int argc, sqlite3_value **argv ){ fulltext_cursor *pCursor; if( argc!=3 && argc!=1 ){ generateError(pContext, "dump_terms", "incorrect arguments"); }else if( sqlite3_value_type(argv[0])!=SQLITE_BLOB || sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){ generateError(pContext, "dump_terms", "illegal first argument"); }else{ fulltext_vtab *v; fts2Hash terms; sqlite3_stmt *s = NULL; int rc; memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor)); v = cursor_vtab(pCursor); /* If passed only the cursor column, get all segments. Otherwise ** get the segment described by the following two arguments. */ if( argc==1 ){ rc = sql_get_statement(v, SEGDIR_SELECT_ALL_STMT, &s); }else{ rc = sql_get_statement(v, SEGDIR_SELECT_SEGMENT_STMT, &s); if( rc==SQLITE_OK ){ rc = sqlite3_bind_int(s, 1, sqlite3_value_int(argv[1])); if( rc==SQLITE_OK ){ rc = sqlite3_bind_int(s, 2, sqlite3_value_int(argv[2])); } } } if( rc!=SQLITE_OK ){ generateError(pContext, "dump_terms", NULL); return; } /* Collect the terms for each segment. */ sqlite3Fts2HashInit(&terms, FTS2_HASH_STRING, 1); while( (rc = sqlite3_step(s))==SQLITE_ROW ){ rc = collectSegmentTerms(v, s, &terms); if( rc!=SQLITE_OK ) break; } if( rc!=SQLITE_DONE ){ sqlite3_reset(s); generateError(pContext, "dump_terms", NULL); }else{ const int nTerms = fts2HashCount(&terms); if( nTerms>0 ){ rc = generateTermsResult(pContext, &terms); if( rc==SQLITE_NOMEM ){ generateError(pContext, "dump_terms", "out of memory"); }else{ assert( rc==SQLITE_OK ); } }else if( argc==3 ){ /* The specific segment asked for could not be found. */ generateError(pContext, "dump_terms", "segment not found"); }else{ /* No segments found. */ /* TODO(shess): It should be impossible to reach this. This ** case can only happen for an empty table, in which case ** SQLite has no rows to call this function on. */ sqlite3_result_null(pContext); } } sqlite3Fts2HashClear(&terms); } } /* Expand the DL_DEFAULT doclist in pData into a text result in ** pContext. */ static void createDoclistResult(sqlite3_context *pContext, const char *pData, int nData){ DataBuffer dump; DLReader dlReader; assert( pData!=NULL && nData>0 ); dataBufferInit(&dump, 0); dlrInit(&dlReader, DL_DEFAULT, pData, nData); for( ; !dlrAtEnd(&dlReader); dlrStep(&dlReader) ){ char buf[256]; PLReader plReader; plrInit(&plReader, &dlReader); if( DL_DEFAULT==DL_DOCIDS || plrAtEnd(&plReader) ){ sqlite3_snprintf(sizeof(buf), buf, "[%lld] ", dlrDocid(&dlReader)); dataBufferAppend(&dump, buf, strlen(buf)); }else{ int iColumn = plrColumn(&plReader); sqlite3_snprintf(sizeof(buf), buf, "[%lld %d[", dlrDocid(&dlReader), iColumn); dataBufferAppend(&dump, buf, strlen(buf)); for( ; !plrAtEnd(&plReader); plrStep(&plReader) ){ if( plrColumn(&plReader)!=iColumn ){ iColumn = plrColumn(&plReader); sqlite3_snprintf(sizeof(buf), buf, "] %d[", iColumn); assert( dump.nData>0 ); dump.nData--; /* Overwrite trailing space. */ assert( dump.pData[dump.nData]==' '); dataBufferAppend(&dump, buf, strlen(buf)); } if( DL_DEFAULT==DL_POSITIONS_OFFSETS ){ sqlite3_snprintf(sizeof(buf), buf, "%d,%d,%d ", plrPosition(&plReader), plrStartOffset(&plReader), plrEndOffset(&plReader)); }else if( DL_DEFAULT==DL_POSITIONS ){ sqlite3_snprintf(sizeof(buf), buf, "%d ", plrPosition(&plReader)); }else{ assert( NULL=="Unhandled DL_DEFAULT value"); } dataBufferAppend(&dump, buf, strlen(buf)); } plrDestroy(&plReader); assert( dump.nData>0 ); dump.nData--; /* Overwrite trailing space. */ assert( dump.pData[dump.nData]==' '); dataBufferAppend(&dump, "]] ", 3); } } dlrDestroy(&dlReader); assert( dump.nData>0 ); dump.nData--; /* Overwrite trailing space. */ assert( dump.pData[dump.nData]==' '); dump.pData[dump.nData] = '\0'; assert( dump.nData>0 ); /* Passes ownership of dump's buffer to pContext. */ sqlite3_result_text(pContext, dump.pData, dump.nData, sqlite3_free); dump.pData = NULL; dump.nData = dump.nCapacity = 0; } /* Implements dump_doclist() for use in inspecting the fts2 index from ** tests. TEXT result containing a string representation of the ** doclist for the indicated term. dump_doclist(t, term, level, idx) ** dumps the doclist for term from the segment specified by level, idx ** (in %_segdir), while dump_doclist(t, term) dumps the logical ** doclist for the term across all segments. The per-segment doclist ** can contain deletions, while the full-index doclist will not ** (deletions are omitted). ** ** Result formats differ with the setting of DL_DEFAULTS. Examples: ** ** DL_DOCIDS: [1] [3] [7] ** DL_POSITIONS: [1 0[0 4] 1[17]] [3 1[5]] ** DL_POSITIONS_OFFSETS: [1 0[0,0,3 4,23,26] 1[17,102,105]] [3 1[5,20,23]] ** ** In each case the number after the outer '[' is the docid. In the ** latter two cases, the number before the inner '[' is the column ** associated with the values within. For DL_POSITIONS the numbers ** within are the positions, for DL_POSITIONS_OFFSETS they are the ** position, the start offset, and the end offset. */ static void dumpDoclistFunc( sqlite3_context *pContext, int argc, sqlite3_value **argv ){ fulltext_cursor *pCursor; if( argc!=2 && argc!=4 ){ generateError(pContext, "dump_doclist", "incorrect arguments"); }else if( sqlite3_value_type(argv[0])!=SQLITE_BLOB || sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){ generateError(pContext, "dump_doclist", "illegal first argument"); }else if( sqlite3_value_text(argv[1])==NULL || sqlite3_value_text(argv[1])[0]=='\0' ){ generateError(pContext, "dump_doclist", "empty second argument"); }else{ const char *pTerm = (const char *)sqlite3_value_text(argv[1]); const int nTerm = strlen(pTerm); fulltext_vtab *v; int rc; DataBuffer doclist; memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor)); v = cursor_vtab(pCursor); dataBufferInit(&doclist, 0); /* termSelect() yields the same logical doclist that queries are ** run against. */ if( argc==2 ){ rc = termSelect(v, v->nColumn, pTerm, nTerm, 0, DL_DEFAULT, &doclist); }else{ sqlite3_stmt *s = NULL; /* Get our specific segment's information. */ rc = sql_get_statement(v, SEGDIR_SELECT_SEGMENT_STMT, &s); if( rc==SQLITE_OK ){ rc = sqlite3_bind_int(s, 1, sqlite3_value_int(argv[2])); if( rc==SQLITE_OK ){ rc = sqlite3_bind_int(s, 2, sqlite3_value_int(argv[3])); } } if( rc==SQLITE_OK ){ rc = sqlite3_step(s); if( rc==SQLITE_DONE ){ dataBufferDestroy(&doclist); generateError(pContext, "dump_doclist", "segment not found"); return; } /* Found a segment, load it into doclist. */ if( rc==SQLITE_ROW ){ const sqlite_int64 iLeavesEnd = sqlite3_column_int64(s, 1); const char *pData = sqlite3_column_blob(s, 2); const int nData = sqlite3_column_bytes(s, 2); /* loadSegment() is used by termSelect() to load each ** segment's data. */ rc = loadSegment(v, pData, nData, iLeavesEnd, pTerm, nTerm, 0, &doclist); if( rc==SQLITE_OK ){ rc = sqlite3_step(s); /* Should not have more than one matching segment. */ if( rc!=SQLITE_DONE ){ sqlite3_reset(s); dataBufferDestroy(&doclist); generateError(pContext, "dump_doclist", "invalid segdir"); return; } rc = SQLITE_OK; } } } sqlite3_reset(s); } if( rc==SQLITE_OK ){ if( doclist.nData>0 ){ createDoclistResult(pContext, doclist.pData, doclist.nData); }else{ /* TODO(shess): This can happen if the term is not present, or ** if all instances of the term have been deleted and this is ** an all-index dump. It may be interesting to distinguish ** these cases. */ sqlite3_result_text(pContext, "", 0, SQLITE_STATIC); } }else if( rc==SQLITE_NOMEM ){ /* Handle out-of-memory cases specially because if they are ** generated in fts2 code they may not be reflected in the db ** handle. */ /* TODO(shess): Handle this more comprehensively. ** sqlite3ErrStr() has what I need, but is internal. */ generateError(pContext, "dump_doclist", "out of memory"); }else{ generateError(pContext, "dump_doclist", NULL); } dataBufferDestroy(&doclist); } } #endif /* ** This routine implements the xFindFunction method for the FTS2 ** virtual table. */ static int fulltextFindFunction( sqlite3_vtab *pVtab, int nArg, const char *zName, void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), void **ppArg ){ if( strcmp(zName,"snippet")==0 ){ *pxFunc = snippetFunc; return 1; }else if( strcmp(zName,"offsets")==0 ){ *pxFunc = snippetOffsetsFunc; return 1; }else if( strcmp(zName,"optimize")==0 ){ *pxFunc = optimizeFunc; return 1; #ifdef SQLITE_TEST /* NOTE(shess): These functions are present only for testing ** purposes. No particular effort is made to optimize their ** execution or how they build their results. */ }else if( strcmp(zName,"dump_terms")==0 ){ /* fprintf(stderr, "Found dump_terms\n"); */ *pxFunc = dumpTermsFunc; return 1; }else if( strcmp(zName,"dump_doclist")==0 ){ /* fprintf(stderr, "Found dump_doclist\n"); */ *pxFunc = dumpDoclistFunc; return 1; #endif } return 0; } /* ** Rename an fts2 table. */ |
︙ | |||
5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 | 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 | + + + + + - + | ** the two scalar functions. If this is successful, register the ** module with sqlite. */ if( SQLITE_OK==rc && SQLITE_OK==(rc = sqlite3Fts2InitHashTable(db, pHash, "fts2_tokenizer")) && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", -1)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", -1)) #ifdef SQLITE_TEST && SQLITE_OK==(rc = sqlite3_overload_function(db, "dump_terms", -1)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "dump_doclist", -1)) #endif ){ return sqlite3_create_module_v2( db, "fts2", &fts2Module, (void *)pHash, hashDestroy ); } |
︙ |
Changes to SQLite.Interop/FTS2/fts2_hash.c.
︙ | |||
25 26 27 28 29 30 31 32 33 | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | + + + + - - + + + + + | */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) #include <assert.h> #include <stdlib.h> #include <string.h> #include "sqlite3.h" #include "fts2_hash.h" /* ** Malloc and Free functions */ |
︙ | |||
54 55 56 57 58 59 60 | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | - - - + - + - + | assert( keyClass>=FTS2_HASH_STRING && keyClass<=FTS2_HASH_BINARY ); pNew->keyClass = keyClass; pNew->copyKey = copyKey; pNew->first = 0; pNew->count = 0; pNew->htsize = 0; pNew->ht = 0; |
︙ | |||
188 189 190 191 192 193 194 | 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | - + - + | */ static void rehash(fts2Hash *pH, int new_size){ struct _fts2ht *new_ht; /* The new hash table */ fts2HashElem *elem, *next_elem; /* For looping over existing elements */ int (*xHash)(const void*,int); /* The hash function */ assert( (new_size & (new_size-1))==0 ); |
︙ | |||
256 257 258 259 260 261 262 | 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | - + - + | pEntry->chain = elem->next; } pEntry->count--; if( pEntry->count<=0 ){ pEntry->chain = 0; } if( pH->copyKey && elem->pKey ){ |
︙ | |||
329 330 331 332 333 334 335 | 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | - + - + - + - + | removeElementGivenHash(pH,elem,h); }else{ elem->data = data; } return old_data; } if( data==0 ) return 0; |
︙ |
Changes to SQLite.Interop/FTS2/fts2_hash.h.
︙ | |||
30 31 32 33 34 35 36 | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | - - | ** this structure opaque. */ struct fts2Hash { char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ char copyKey; /* True if copy of key made on insert */ int count; /* Number of entries in this table */ fts2HashElem *first; /* The first element of the array */ |
︙ |
Changes to SQLite.Interop/FTS2/fts2_porter.c.
︙ | |||
25 26 27 28 29 30 31 | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | - | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) #include <assert.h> #include <stdlib.h> #include <stdio.h> #include <string.h> |
︙ | |||
62 63 64 65 66 67 68 | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | - + - + - + - + | ** Create a new tokenizer instance. */ static int porterCreate( int argc, const char * const *argv, sqlite3_tokenizer **ppTokenizer ){ porter_tokenizer *t; |
︙ | |||
116 117 118 119 120 121 122 | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | - - + + | /* ** Close a tokenization cursor previously opened by a call to ** porterOpen() above. */ static int porterClose(sqlite3_tokenizer_cursor *pCursor){ porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; |
︙ | |||
599 600 601 602 603 604 605 | 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 | - + | c->iOffset++; } if( c->iOffset>iStartOffset ){ int n = c->iOffset-iStartOffset; if( n>c->nAllocated ){ c->nAllocated = n+20; |
︙ |
Changes to SQLite.Interop/FTS2/fts2_tokenizer.c.
︙ | |||
235 236 237 238 239 240 241 | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | - + | sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC); sqlite3_step(pStmt); return sqlite3_finalize(pStmt); } static |
︙ | |||
268 269 270 271 272 273 274 | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | - + | /* ** Implementation of the scalar function fts2_tokenizer_internal_test(). ** This function is used for testing only, it is not included in the ** build unless SQLITE_TEST is defined. ** ** The purpose of this is to test that the fts2_tokenizer() function |
︙ | |||
292 293 294 295 296 297 298 | 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | - + - + - + | int rc; const sqlite3_tokenizer_module *p1; const sqlite3_tokenizer_module *p2; sqlite3 *db = (sqlite3 *)sqlite3_user_data(context); /* Test the query function */ sqlite3Fts2SimpleTokenizerModule(&p1); |
︙ |
Changes to SQLite.Interop/FTS2/fts2_tokenizer1.c.
︙ | |||
25 26 27 28 29 30 31 | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | - | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) #include <assert.h> #include <stdlib.h> #include <stdio.h> #include <string.h> |
︙ | |||
61 62 63 64 65 66 67 | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | - + + - + - + + - + - + | */ static int simpleCreate( int argc, const char * const *argv, sqlite3_tokenizer **ppTokenizer ){ simple_tokenizer *t; |
︙ | |||
139 140 141 142 143 144 145 | 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | - - + + | /* ** Close a tokenization cursor previously opened by a call to ** simpleOpen() above. */ static int simpleClose(sqlite3_tokenizer_cursor *pCursor){ simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; |
︙ | |||
178 179 180 181 182 183 184 | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | - + - + | c->iOffset++; } if( c->iOffset>iStartOffset ){ int i, n = c->iOffset-iStartOffset; if( n>c->nTokenAllocated ){ c->nTokenAllocated = n+20; |
︙ |
Changes to SQLite.Interop/SQLite.Interop.rc.
︙ | |||
9 10 11 12 13 14 15 | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | - + - - | // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// |
︙ | |||
70 71 72 73 74 75 76 | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | - + - + | BLOCK "040904b0" BEGIN VALUE "Comments", "http://sqlite.phxsoftware.com" VALUE "FileDescription", "System.Data.SQLite Interop Library" VALUE "FileVersion", "1.0.67.0" VALUE "InternalName", "SQLite.Interop.DLL" VALUE "LegalCopyright", "Released to the public domain" |
︙ |
Changes to SQLite.Interop/SQLite.Interop.vcproj.
︙ | |||
8 9 10 11 12 13 14 | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | - - - - - - | Keyword="Win32Proj" TargetFrameworkVersion="131072" > <Platforms> <Platform Name="Win32" /> |
︙ | |||
79 80 81 82 83 84 85 | 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ModuleDefinitionFile="src\sqlite3.def" EmbedManagedResourceFile="" DelayLoadDLLs="advapi32.dll" RandomizedBaseAddress="1" DataExecutionPrevention="0" ImportLibrary="" TargetMachine="1" |
︙ | |||
449 450 451 452 453 454 455 | 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <Tool Name="VCAppVerifierTool" /> <Tool Name="VCPostBuildEventTool" CommandLine="" /> |
︙ | |||
778 779 780 781 782 783 784 | 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <Tool Name="VCAppVerifierTool" /> <Tool Name="VCPostBuildEventTool" CommandLine="" /> |
︙ | |||
1065 1066 1067 1068 1069 1070 1071 | 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <FileConfiguration Name="Release|Win32" > <Tool Name="VCManagedResourceCompilerTool" ResourceFileName="$(IntDir)\System.Data.SQLite.$(InputName).resources" /> |
︙ |
Added SQLite.Interop/SQLite.Interop.vcxproj.