Fossil

Check-in [2ec0dc29f3]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Update the built-in SQLite to the latest 3.34.0 alpha.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 2ec0dc29f386cc5dc16a34f64e3f23be89a899717d5b713cf11cc46845086ebe
User & Date: drh 2020-10-13 12:19:22.850
Context
2020-10-13
13:26
Improved identification of the source of phantoms when they are named in a cluster but nowhere else. check-in: cd624d4ff2 user: drh tags: trunk
12:19
Update the built-in SQLite to the latest 3.34.0 alpha. check-in: 2ec0dc29f3 user: drh tags: trunk
08:35
Typo fix check-in: 9c67804a16 user: wyoung tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/shell.c.
11196
11197
11198
11199
11200
11201
11202


11203
11204
11205
11206
11207
11208
11209
#define SHFLG_Lookaside      0x00000002 /* Lookaside memory is used */
#define SHFLG_Backslash      0x00000004 /* The --backslash option is used */
#define SHFLG_PreserveRowid  0x00000008 /* .dump preserves rowid values */
#define SHFLG_Newlines       0x00000010 /* .dump --newline flag */
#define SHFLG_CountChanges   0x00000020 /* .changes setting */
#define SHFLG_Echo           0x00000040 /* .echo or --echo setting */
#define SHFLG_HeaderSet      0x00000080 /* .header has been used */



/*
** Macros for testing and setting shellFlgs
*/
#define ShellHasFlag(P,X)    (((P)->shellFlgs & (X))!=0)
#define ShellSetFlag(P,X)    ((P)->shellFlgs|=(X))
#define ShellClearFlag(P,X)  ((P)->shellFlgs&=(~(X)))







>
>







11196
11197
11198
11199
11200
11201
11202
11203
11204
11205
11206
11207
11208
11209
11210
11211
#define SHFLG_Lookaside      0x00000002 /* Lookaside memory is used */
#define SHFLG_Backslash      0x00000004 /* The --backslash option is used */
#define SHFLG_PreserveRowid  0x00000008 /* .dump preserves rowid values */
#define SHFLG_Newlines       0x00000010 /* .dump --newline flag */
#define SHFLG_CountChanges   0x00000020 /* .changes setting */
#define SHFLG_Echo           0x00000040 /* .echo or --echo setting */
#define SHFLG_HeaderSet      0x00000080 /* .header has been used */
#define SHFLG_DumpDataOnly   0x00000100 /* .dump show data only */
#define SHFLG_DumpNoSys      0x00000200 /* .dump omits system tables */

/*
** Macros for testing and setting shellFlgs
*/
#define ShellHasFlag(P,X)    (((P)->shellFlgs & (X))!=0)
#define ShellSetFlag(P,X)    ((P)->shellFlgs|=(X))
#define ShellClearFlag(P,X)  ((P)->shellFlgs&=(~(X)))
13722
13723
13724
13725
13726
13727
13728


13729
13730
13731
13732
13733
13734
13735


13736
13737
13738
13739
13740
13741
13742
  ShellState *p = (ShellState *)pArg;

  UNUSED_PARAMETER(azNotUsed);
  if( nArg!=3 || azArg==0 ) return 0;
  zTable = azArg[0];
  zType = azArg[1];
  zSql = azArg[2];



  if( strcmp(zTable, "sqlite_sequence")==0 ){
    raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
  }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
    raw_printf(p->out, "ANALYZE sqlite_schema;\n");
  }else if( strncmp(zTable, "sqlite_", 7)==0 ){
    return 0;


  }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
    char *zIns;
    if( !p->writableSchema ){
      raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
      p->writableSchema = 1;
    }
    zIns = sqlite3_mprintf(







>
>

|
|
|
|


>
>







13724
13725
13726
13727
13728
13729
13730
13731
13732
13733
13734
13735
13736
13737
13738
13739
13740
13741
13742
13743
13744
13745
13746
13747
13748
  ShellState *p = (ShellState *)pArg;

  UNUSED_PARAMETER(azNotUsed);
  if( nArg!=3 || azArg==0 ) return 0;
  zTable = azArg[0];
  zType = azArg[1];
  zSql = azArg[2];
  int dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
  int noSys    = (p->shellFlgs & SHFLG_DumpNoSys)!=0;

  if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
    if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
  }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
    if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
  }else if( strncmp(zTable, "sqlite_", 7)==0 ){
    return 0;
  }else if( dataOnly ){
    /* no-op */
  }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
    char *zIns;
    if( !p->writableSchema ){
      raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
      p->writableSchema = 1;
    }
    zIns = sqlite3_mprintf(
13901
13902
13903
13904
13905
13906
13907
13908
13909


13910
13911
13912
13913
13914
13915
13916
  ".check GLOB              Fail if output since .testcase does not match",
  ".clone NEWDB             Clone data into NEWDB from the existing database",
  ".databases               List names and files of attached databases",
  ".dbconfig ?op? ?val?     List or change sqlite3_db_config() options",
  ".dbinfo ?DB?             Show status information about the database",
  ".dump ?TABLE?            Render database content as SQL",
  "   Options:",
  "     --preserve-rowids      Include ROWID values in the output",
  "     --newlines             Allow unescaped newline characters in output",


  "   TABLE is a LIKE pattern for the tables to dump",
  "   Additional LIKE patterns can be given in subsequent arguments",
  ".echo on|off             Turn command echo on or off",
  ".eqp on|off|full|...     Enable or disable automatic EXPLAIN QUERY PLAN",
  "   Other Modes:",
#ifdef SQLITE_DEBUG
  "      test                  Show raw EXPLAIN QUERY PLAN output",







|

>
>







13907
13908
13909
13910
13911
13912
13913
13914
13915
13916
13917
13918
13919
13920
13921
13922
13923
13924
  ".check GLOB              Fail if output since .testcase does not match",
  ".clone NEWDB             Clone data into NEWDB from the existing database",
  ".databases               List names and files of attached databases",
  ".dbconfig ?op? ?val?     List or change sqlite3_db_config() options",
  ".dbinfo ?DB?             Show status information about the database",
  ".dump ?TABLE?            Render database content as SQL",
  "   Options:",
  "     --data-only            Output only INSERT statements",
  "     --newlines             Allow unescaped newline characters in output",
  "     --nosys                Omit system tables (ex: \"sqlite_stat1\")",
  "     --preserve-rowids      Include ROWID values in the output",
  "   TABLE is a LIKE pattern for the tables to dump",
  "   Additional LIKE patterns can be given in subsequent arguments",
  ".echo on|off             Turn command echo on or off",
  ".eqp on|off|full|...     Enable or disable automatic EXPLAIN QUERY PLAN",
  "   Other Modes:",
#ifdef SQLITE_DEBUG
  "      test                  Show raw EXPLAIN QUERY PLAN output",
14027
14028
14029
14030
14031
14032
14033
14034
14035

14036
14037
14038
14039
14040
14041
14042
  "   --no-rowids              Do not attempt to recover rowid values",
  "                            that are not also INTEGER PRIMARY KEYs",
#endif
  ".restore ?DB? FILE       Restore content of DB (default \"main\") from FILE",
  ".save FILE               Write in-memory database into FILE",
  ".scanstats on|off        Turn sqlite3_stmt_scanstatus() metrics on or off",
  ".schema ?PATTERN?        Show the CREATE statements matching PATTERN",
  "     Options:",
  "         --indent            Try to pretty-print the schema",

  ".selftest ?OPTIONS?      Run tests defined in the SELFTEST table",
  "    Options:",
  "       --init               Create a new SELFTEST table",
  "       -v                   Verbose output",
  ".separator COL ?ROW?     Change the column and row separators",
#if defined(SQLITE_ENABLE_SESSION)
  ".session ?NAME? CMD ...  Create or control sessions",







|
|
>







14035
14036
14037
14038
14039
14040
14041
14042
14043
14044
14045
14046
14047
14048
14049
14050
14051
  "   --no-rowids              Do not attempt to recover rowid values",
  "                            that are not also INTEGER PRIMARY KEYs",
#endif
  ".restore ?DB? FILE       Restore content of DB (default \"main\") from FILE",
  ".save FILE               Write in-memory database into FILE",
  ".scanstats on|off        Turn sqlite3_stmt_scanstatus() metrics on or off",
  ".schema ?PATTERN?        Show the CREATE statements matching PATTERN",
  "   Options:",
  "      --indent             Try to pretty-print the schema",
  "      --nosys              Omit objects whose names start with \"sqlite_\"",
  ".selftest ?OPTIONS?      Run tests defined in the SELFTEST table",
  "    Options:",
  "       --init               Create a new SELFTEST table",
  "       -v                   Verbose output",
  ".separator COL ?ROW?     Change the column and row separators",
#if defined(SQLITE_ENABLE_SESSION)
  ".session ?NAME? CMD ...  Create or control sessions",
17703
17704
17705
17706
17707
17708
17709

17710

17711
17712
17713
17714
17715
17716
17717
17718
17719
17720
17721
17722
17723
17724
17725
17726
17727
17728






17729
17730
17731
17732
17733
17734
17735
17736
17737
17738
17739
17740
17741
17742
17743
17744

17745
17746
17747
17748
17749

17750
17751
17752
17753
17754
17755
17756
17757
17758
17759
17760
17761
17762
17763
17764
17765
17766

17767
17768
17769
17770
17771
17772
17773
17774

17775
17776
17777
17778
17779
17780
17781

17782

17783
17784
17785
17786
17787
17788
17789

  if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
    char *zLike = 0;
    char *zSql;
    int i;
    int savedShowHeader = p->showHeader;
    int savedShellFlags = p->shellFlgs;

    ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo);

    for(i=1; i<nArg; i++){
      if( azArg[i][0]=='-' ){
        const char *z = azArg[i]+1;
        if( z[0]=='-' ) z++;
        if( strcmp(z,"preserve-rowids")==0 ){
#ifdef SQLITE_OMIT_VIRTUALTABLE
          raw_printf(stderr, "The --preserve-rowids option is not compatible"
                             " with SQLITE_OMIT_VIRTUALTABLE\n");
          rc = 1;
          sqlite3_free(zLike);
          goto meta_command_exit;
#else
          ShellSetFlag(p, SHFLG_PreserveRowid);
#endif
        }else
        if( strcmp(z,"newlines")==0 ){
          ShellSetFlag(p, SHFLG_Newlines);
        }else






        {
          raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
          rc = 1;
          sqlite3_free(zLike);
          goto meta_command_exit;
        }
      }else if( zLike ){
        zLike = sqlite3_mprintf("%z OR name LIKE %Q ESCAPE '\\'",
                zLike, azArg[i]);
      }else{
        zLike = sqlite3_mprintf("name LIKE %Q ESCAPE '\\'", azArg[i]);
      }
    }

    open_db(p, 0);


    /* When playing back a "dump", the content might appear in an order
    ** which causes immediate foreign key constraints to be violated.
    ** So disable foreign-key constraint enforcement to prevent problems. */
    raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
    raw_printf(p->out, "BEGIN TRANSACTION;\n");

    p->writableSchema = 0;
    p->showHeader = 0;
    /* Set writable_schema=ON since doing so forces SQLite to initialize
    ** as much of the schema as it can even if the sqlite_schema table is
    ** corrupt. */
    sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
    p->nErr = 0;
    if( zLike==0 ) zLike = sqlite3_mprintf("true");
    zSql = sqlite3_mprintf(
      "SELECT name, type, sql FROM sqlite_schema "
      "WHERE (%s) AND type=='table'"
      "  AND sql NOT NULL"
      " ORDER BY tbl_name='sqlite_sequence', rowid",
      zLike
    );
    run_schema_dump_query(p,zSql);
    sqlite3_free(zSql);

    zSql = sqlite3_mprintf(
      "SELECT sql FROM sqlite_schema "
      "WHERE (%s) AND sql NOT NULL"
      "  AND type IN ('index','trigger','view')",
      zLike
    );
    run_table_dump_query(p, zSql);
    sqlite3_free(zSql);

    sqlite3_free(zLike);
    if( p->writableSchema ){
      raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
      p->writableSchema = 0;
    }
    sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
    sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);

    raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");

    p->showHeader = savedShowHeader;
    p->shellFlgs = savedShellFlags;
  }else

  if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
    if( nArg==2 ){
      setOrClearFlag(p, SHFLG_Echo, azArg[1]);







>
|
>


















>
>
>
>
>
>
















>
|
|
|
|
|
>

















>
|
|
|
|
|
|
|
|
>







>
|
>







17712
17713
17714
17715
17716
17717
17718
17719
17720
17721
17722
17723
17724
17725
17726
17727
17728
17729
17730
17731
17732
17733
17734
17735
17736
17737
17738
17739
17740
17741
17742
17743
17744
17745
17746
17747
17748
17749
17750
17751
17752
17753
17754
17755
17756
17757
17758
17759
17760
17761
17762
17763
17764
17765
17766
17767
17768
17769
17770
17771
17772
17773
17774
17775
17776
17777
17778
17779
17780
17781
17782
17783
17784
17785
17786
17787
17788
17789
17790
17791
17792
17793
17794
17795
17796
17797
17798
17799
17800
17801
17802
17803
17804
17805
17806
17807
17808
17809
17810
17811
17812

  if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
    char *zLike = 0;
    char *zSql;
    int i;
    int savedShowHeader = p->showHeader;
    int savedShellFlags = p->shellFlgs;
    ShellClearFlag(p, 
       SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
       |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
    for(i=1; i<nArg; i++){
      if( azArg[i][0]=='-' ){
        const char *z = azArg[i]+1;
        if( z[0]=='-' ) z++;
        if( strcmp(z,"preserve-rowids")==0 ){
#ifdef SQLITE_OMIT_VIRTUALTABLE
          raw_printf(stderr, "The --preserve-rowids option is not compatible"
                             " with SQLITE_OMIT_VIRTUALTABLE\n");
          rc = 1;
          sqlite3_free(zLike);
          goto meta_command_exit;
#else
          ShellSetFlag(p, SHFLG_PreserveRowid);
#endif
        }else
        if( strcmp(z,"newlines")==0 ){
          ShellSetFlag(p, SHFLG_Newlines);
        }else
        if( strcmp(z,"data-only")==0 ){
          ShellSetFlag(p, SHFLG_DumpDataOnly);
        }else
        if( strcmp(z,"nosys")==0 ){
          ShellSetFlag(p, SHFLG_DumpNoSys);
        }else
        {
          raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
          rc = 1;
          sqlite3_free(zLike);
          goto meta_command_exit;
        }
      }else if( zLike ){
        zLike = sqlite3_mprintf("%z OR name LIKE %Q ESCAPE '\\'",
                zLike, azArg[i]);
      }else{
        zLike = sqlite3_mprintf("name LIKE %Q ESCAPE '\\'", azArg[i]);
      }
    }

    open_db(p, 0);

    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
      /* When playing back a "dump", the content might appear in an order
      ** which causes immediate foreign key constraints to be violated.
      ** So disable foreign-key constraint enforcement to prevent problems. */
      raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
      raw_printf(p->out, "BEGIN TRANSACTION;\n");
    }
    p->writableSchema = 0;
    p->showHeader = 0;
    /* Set writable_schema=ON since doing so forces SQLite to initialize
    ** as much of the schema as it can even if the sqlite_schema table is
    ** corrupt. */
    sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
    p->nErr = 0;
    if( zLike==0 ) zLike = sqlite3_mprintf("true");
    zSql = sqlite3_mprintf(
      "SELECT name, type, sql FROM sqlite_schema "
      "WHERE (%s) AND type=='table'"
      "  AND sql NOT NULL"
      " ORDER BY tbl_name='sqlite_sequence', rowid",
      zLike
    );
    run_schema_dump_query(p,zSql);
    sqlite3_free(zSql);
    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
      zSql = sqlite3_mprintf(
        "SELECT sql FROM sqlite_schema "
        "WHERE (%s) AND sql NOT NULL"
        "  AND type IN ('index','trigger','view')",
        zLike
      );
      run_table_dump_query(p, zSql);
      sqlite3_free(zSql);
    }
    sqlite3_free(zLike);
    if( p->writableSchema ){
      raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
      p->writableSchema = 0;
    }
    sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
    sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
      raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
    }
    p->showHeader = savedShowHeader;
    p->shellFlgs = savedShellFlags;
  }else

  if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
    if( nArg==2 ){
      setOrClearFlag(p, SHFLG_Echo, azArg[1]);
18214
18215
18216
18217
18218
18219
18220
18221
18222
18223
18224
18225
18226
18227
18228
18229
18230
18231
18232
18233
18234
18235
18236
18237
18238
18239
18240
18241
18242
18243
18244
18245
18246
18247
18248
18249
18250
18251
18252
18253
18254
18255
18256
18257
18258
      zSep[0] = sCtx.cRowSep;
      output_c_string(p->out, zSep);
      utf8_printf(p->out, "\n");
    }
    while( (nSkip--)>0 ){
      while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
    }
    zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
    if( zSql==0 ){
      import_cleanup(&sCtx);
      shell_out_of_memory();
    }
    nByte = strlen30(zSql);
    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    import_append_char(&sCtx, 0);    /* To ensure sCtx.z is allocated */
    if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
      char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
      char cSep = '(';
      while( xRead(&sCtx) ){
        zCreate = sqlite3_mprintf("%z%c\n  \"%w\" TEXT", zCreate, cSep, sCtx.z);
        cSep = ',';
        if( sCtx.cTerm!=sCtx.cColSep ) break;
      }
      if( cSep=='(' ){
        sqlite3_free(zCreate);
        import_cleanup(&sCtx);
        utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
        rc = 1;
        goto meta_command_exit;
      }
      zCreate = sqlite3_mprintf("%z\n)", zCreate);
      if( eVerbose>=1 ){
        utf8_printf(p->out, "%s\n", zCreate);
      }
      rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
      sqlite3_free(zCreate);
      if( rc ){
        utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
                sqlite3_errmsg(p->db));
        import_cleanup(&sCtx);
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    }







|








|




















|







18237
18238
18239
18240
18241
18242
18243
18244
18245
18246
18247
18248
18249
18250
18251
18252
18253
18254
18255
18256
18257
18258
18259
18260
18261
18262
18263
18264
18265
18266
18267
18268
18269
18270
18271
18272
18273
18274
18275
18276
18277
18278
18279
18280
18281
      zSep[0] = sCtx.cRowSep;
      output_c_string(p->out, zSep);
      utf8_printf(p->out, "\n");
    }
    while( (nSkip--)>0 ){
      while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
    }
    zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
    if( zSql==0 ){
      import_cleanup(&sCtx);
      shell_out_of_memory();
    }
    nByte = strlen30(zSql);
    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    import_append_char(&sCtx, 0);    /* To ensure sCtx.z is allocated */
    if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
      char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
      char cSep = '(';
      while( xRead(&sCtx) ){
        zCreate = sqlite3_mprintf("%z%c\n  \"%w\" TEXT", zCreate, cSep, sCtx.z);
        cSep = ',';
        if( sCtx.cTerm!=sCtx.cColSep ) break;
      }
      if( cSep=='(' ){
        sqlite3_free(zCreate);
        import_cleanup(&sCtx);
        utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
        rc = 1;
        goto meta_command_exit;
      }
      zCreate = sqlite3_mprintf("%z\n)", zCreate);
      if( eVerbose>=1 ){
        utf8_printf(p->out, "%s\n", zCreate);
      }
      rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
      sqlite3_free(zCreate);
      if( rc ){
        utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
                sqlite3_errmsg(p->db));
        import_cleanup(&sCtx);
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    }
19100
19101
19102
19103
19104
19105
19106

19107
19108
19109
19110
19111
19112
19113
19114
19115
19116
19117
19118






19119
19120
19121
19122
19123
19124
19125
19126
19127
19128
19129
    ShellText sSelect;
    ShellState data;
    char *zErrMsg = 0;
    const char *zDiv = "(";
    const char *zName = 0;
    int iSchema = 0;
    int bDebug = 0;

    int ii;

    open_db(p, 0);
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.cMode = data.mode = MODE_Semi;
    initText(&sSelect);
    for(ii=1; ii<nArg; ii++){
      if( optionMatch(azArg[ii],"indent") ){
        data.cMode = data.mode = MODE_Pretty;
      }else if( optionMatch(azArg[ii],"debug") ){
        bDebug = 1;






      }else if( zName==0 ){
        zName = azArg[ii];
      }else{
        raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
        rc = 1;
        goto meta_command_exit;
      }
    }
    if( zName!=0 ){
      int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
                  || sqlite3_strlike(zName, "sqlite_schema", '\\')==0







>












>
>
>
>
>
>



|







19123
19124
19125
19126
19127
19128
19129
19130
19131
19132
19133
19134
19135
19136
19137
19138
19139
19140
19141
19142
19143
19144
19145
19146
19147
19148
19149
19150
19151
19152
19153
19154
19155
19156
19157
19158
19159
    ShellText sSelect;
    ShellState data;
    char *zErrMsg = 0;
    const char *zDiv = "(";
    const char *zName = 0;
    int iSchema = 0;
    int bDebug = 0;
    int bNoSystemTabs = 0;
    int ii;

    open_db(p, 0);
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.cMode = data.mode = MODE_Semi;
    initText(&sSelect);
    for(ii=1; ii<nArg; ii++){
      if( optionMatch(azArg[ii],"indent") ){
        data.cMode = data.mode = MODE_Pretty;
      }else if( optionMatch(azArg[ii],"debug") ){
        bDebug = 1;
      }else if( optionMatch(azArg[ii],"nosys") ){
        bNoSystemTabs = 1;
      }else if( azArg[ii][0]=='-' ){
        utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
        rc = 1;
        goto meta_command_exit;
      }else if( zName==0 ){
        zName = azArg[ii];
      }else{
        raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
        rc = 1;
        goto meta_command_exit;
      }
    }
    if( zName!=0 ){
      int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
                  || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
19201
19202
19203
19204
19205
19206
19207



19208
19209
19210
19211
19212
19213
19214
19215
        appendText(&sSelect, zQarg, 0);
        if( !bGlob ){
          appendText(&sSelect, " ESCAPE '\\' ", 0);
        }
        appendText(&sSelect, " AND ", 0);
        sqlite3_free(zQarg);
      }



      appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
                           " ORDER BY snum, rowid", 0);
      if( bDebug ){
        utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
      }else{
        rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
      }
      freeText(&sSelect);







>
>
>
|







19231
19232
19233
19234
19235
19236
19237
19238
19239
19240
19241
19242
19243
19244
19245
19246
19247
19248
        appendText(&sSelect, zQarg, 0);
        if( !bGlob ){
          appendText(&sSelect, " ESCAPE '\\' ", 0);
        }
        appendText(&sSelect, " AND ", 0);
        sqlite3_free(zQarg);
      }
      if( bNoSystemTabs ){
        appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
      }
      appendText(&sSelect, "sql IS NOT NULL"
                           " ORDER BY snum, rowid", 0);
      if( bDebug ){
        utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
      }else{
        rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
      }
      freeText(&sSelect);
Changes to src/sqlite3.c.
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.34.0"
#define SQLITE_VERSION_NUMBER 3034000
#define SQLITE_SOURCE_ID      "2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c402e5"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros







|







1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.34.0"
#define SQLITE_VERSION_NUMBER 3034000
#define SQLITE_SOURCE_ID      "2020-10-12 18:09:16 7e17c2f4b7dc9b563d0b4da949bb134dc7c4fc9c86ce03891432a884ca6409d5"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
88943
88944
88945
88946
88947
88948
88949
88950

88951
88952
88953
88954
88955
88956
88957

/* Opcode: Transaction P1 P2 P3 P4 P5
**
** Begin a transaction on database P1 if a transaction is not already
** active.
** If P2 is non-zero, then a write-transaction is started, or if a
** read-transaction is already active, it is upgraded to a write-transaction.
** If P2 is zero, then a read-transaction is started.

**
** P1 is the index of the database file on which the transaction is
** started.  Index 0 is the main database file and index 1 is the
** file used for temporary tables.  Indices of 2 or more are used for
** attached databases.
**
** If a write-transaction is started and the Vdbe.usesStmtJournal flag is







|
>







88943
88944
88945
88946
88947
88948
88949
88950
88951
88952
88953
88954
88955
88956
88957
88958

/* Opcode: Transaction P1 P2 P3 P4 P5
**
** Begin a transaction on database P1 if a transaction is not already
** active.
** If P2 is non-zero, then a write-transaction is started, or if a
** read-transaction is already active, it is upgraded to a write-transaction.
** If P2 is zero, then a read-transaction is started.  If P2 is 2 or more
** then an exclusive transaction is started.
**
** P1 is the index of the database file on which the transaction is
** started.  Index 0 is the main database file and index 1 is the
** file used for temporary tables.  Indices of 2 or more are used for
** attached databases.
**
** If a write-transaction is started and the Vdbe.usesStmtJournal flag is
88977
88978
88979
88980
88981
88982
88983

88984
88985
88986
88987
88988
88989
88990
*/
case OP_Transaction: {
  Btree *pBt;
  int iMeta = 0;

  assert( p->bIsReader );
  assert( p->readOnly==0 || pOp->p2==0 );

  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  assert( DbMaskTest(p->btreeMask, pOp->p1) );
  if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
    rc = SQLITE_READONLY;
    goto abort_due_to_error;
  }
  pBt = db->aDb[pOp->p1].pBt;







>







88978
88979
88980
88981
88982
88983
88984
88985
88986
88987
88988
88989
88990
88991
88992
*/
case OP_Transaction: {
  Btree *pBt;
  int iMeta = 0;

  assert( p->bIsReader );
  assert( p->readOnly==0 || pOp->p2==0 );
  assert( pOp->p2>=0 && pOp->p2<=2 );
  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  assert( DbMaskTest(p->btreeMask, pOp->p1) );
  if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
    rc = SQLITE_READONLY;
    goto abort_due_to_error;
  }
  pBt = db->aDb[pOp->p1].pBt;
89840
89841
89842
89843
89844
89845
89846
89847
89848
89849
89850
89851
89852
89853
89854
89855
89856
89857
89858

89859
89860
89861
89862
89863
89864
89865
89866
89867
89868
89869
89870
89871
89872
89873
89874
89875
89876
89877
89878
89879
89880
89881
89882
89883
89884
89885
89886
89887
89888
89889
89890
89891
89892
89893
89894
89895
89896
89897
89898
89899




89900
89901
89902
89903
89904
89905
89906
89907
89908
89909
89910
89911
89912
89913
89914
89915
89916
89917
89918
89919
89920
89921
89922
89923
89924
89925
89926
    assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
    pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */
  }
  break;
}


/* Opcode: SeekScan  P1 * * * *
** Synopsis: Scan-ahead up to P1 rows
**
** This opcode is a prefix opcode to OP_SeekGE.  In other words, this
** opcode must be immediately followed by OP_SeekGE.  Furthermore, the
** OP_SeekGE must be followed by OP_IdxGT.  These constraints are
** checked by assert() statements.
**
** This opcode uses the P1 through P4 operands of the subsequent
** OP_SeekGE.  In the text that follows, the operands of the subsequent
** OP_SeekGE opcode are denoted as SeekOP.P1 through SeekOP.P4.   Only
** the P1 operand of this opcode is used, and it is denoted as This.P1.

**
** This opcode helps to optimize IN operators on a multi-column index
** where the IN operator is on the later terms of the index by avoiding
** unnecessary seeks on the btree, substituting steps to the next row
** of the b-tree instead.  A correct answer is obtained if this opcode
** is omitted or is a no-op.
**
** The SeekGE.P3 and SeekGE.P4 operands identify an unpacked key which
** is the desired entry that we want the cursor SeekGE.P1 to be pointing
** to.  Call this SeekGE.P4/P5 row the "target".
**
** If the SeekGE.P1 cursor is not currently pointing to a valid row,
** then this opcode is a no-op and control passes through into the OP_SeekGE.
**
** If the SeekGE.P1 cursor is pointing to a valid row, then that row
** might be the target row, or it might be near and slightly before the
** target row.  This opcode attempts to position the cursor on the target
** row by, perhaps stepping by invoking sqlite3BtreeStep() on the cursor
** between 0 and This.P1 times.
**
** There are three possible outcomes from this opcode:<ol>
**
** <li> If after This.P1 steps, the cursor is still point to a place that
**      is earlier in the btree than the target row,
**      then fall through into the subsquence OP_SeekGE opcode.
**
** <li> If the cursor is successfully moved to the target row by 0 or more
**      sqlite3BtreeNext() calls, then jump to the first instruction after the
**      OP_IdxGT opcode - or in other words, skip the next two opcodes.
**
** <li> If the cursor ends up past the target row (indicating the the target
**      row does not exist in the btree) then jump to SeekOP.P2.
** </ol>
*/
case OP_SeekScan: {
  VdbeCursor *pC;
  int res;
  int n;
  UnpackedRecord r;

  assert( pOp[1].opcode==OP_SeekGE );




  assert( pOp[2].opcode==OP_IdxGT );
  assert( pOp[1].p1==pOp[2].p1 );
  assert( pOp[1].p2==pOp[2].p2 );
  assert( pOp[1].p3==pOp[2].p3 );
  assert( pOp[1].p4.i==pOp[2].p4.i );
  assert( pOp->p1>0 );
  pC = p->apCsr[pOp[1].p1];
  assert( pC!=0 );
  assert( pC->eCurType==CURTYPE_BTREE );
  assert( !pC->isTable );
  if( !sqlite3BtreeCursorIsValidNN(pC->uc.pCursor) ){
#ifdef SQLITE_DEBUG
     if( db->flags&SQLITE_VdbeTrace ){
       printf("... cursor not valid - fall through\n");
     }
#endif
    break;
  }
  n = pOp->p1;
  assert( n>=1 );
  r.pKeyInfo = pC->pKeyInfo;
  r.nField = (u16)pOp[1].p4.i;
  r.default_rc = 0;
  r.aMem = &aMem[pOp[1].p3];
#ifdef SQLITE_DEBUG
  {
    int i;







|



|
<





|
>

















|









|
|








|



>
>
>
>
|
|
|
|
|













|
|







89842
89843
89844
89845
89846
89847
89848
89849
89850
89851
89852
89853

89854
89855
89856
89857
89858
89859
89860
89861
89862
89863
89864
89865
89866
89867
89868
89869
89870
89871
89872
89873
89874
89875
89876
89877
89878
89879
89880
89881
89882
89883
89884
89885
89886
89887
89888
89889
89890
89891
89892
89893
89894
89895
89896
89897
89898
89899
89900
89901
89902
89903
89904
89905
89906
89907
89908
89909
89910
89911
89912
89913
89914
89915
89916
89917
89918
89919
89920
89921
89922
89923
89924
89925
89926
89927
89928
89929
89930
89931
89932
    assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
    pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */
  }
  break;
}


/* Opcode: SeekScan  P1 P2 * * *
** Synopsis: Scan-ahead up to P1 rows
**
** This opcode is a prefix opcode to OP_SeekGE.  In other words, this
** opcode must be immediately followed by OP_SeekGE. This constraint is

** checked by assert() statements.
**
** This opcode uses the P1 through P4 operands of the subsequent
** OP_SeekGE.  In the text that follows, the operands of the subsequent
** OP_SeekGE opcode are denoted as SeekOP.P1 through SeekOP.P4.   Only
** the P1 and P2 operands of this opcode are also used, and  are called
** This.P1 and This.P2.
**
** This opcode helps to optimize IN operators on a multi-column index
** where the IN operator is on the later terms of the index by avoiding
** unnecessary seeks on the btree, substituting steps to the next row
** of the b-tree instead.  A correct answer is obtained if this opcode
** is omitted or is a no-op.
**
** The SeekGE.P3 and SeekGE.P4 operands identify an unpacked key which
** is the desired entry that we want the cursor SeekGE.P1 to be pointing
** to.  Call this SeekGE.P4/P5 row the "target".
**
** If the SeekGE.P1 cursor is not currently pointing to a valid row,
** then this opcode is a no-op and control passes through into the OP_SeekGE.
**
** If the SeekGE.P1 cursor is pointing to a valid row, then that row
** might be the target row, or it might be near and slightly before the
** target row.  This opcode attempts to position the cursor on the target
** row by, perhaps by invoking sqlite3BtreeStep() on the cursor
** between 0 and This.P1 times.
**
** There are three possible outcomes from this opcode:<ol>
**
** <li> If after This.P1 steps, the cursor is still point to a place that
**      is earlier in the btree than the target row,
**      then fall through into the subsquence OP_SeekGE opcode.
**
** <li> If the cursor is successfully moved to the target row by 0 or more
**      sqlite3BtreeNext() calls, then jump to This.P2, which will land just
**      past the OP_IdxGT opcode that follows the OP_SeekGE.
**
** <li> If the cursor ends up past the target row (indicating the the target
**      row does not exist in the btree) then jump to SeekOP.P2.
** </ol>
*/
case OP_SeekScan: {
  VdbeCursor *pC;
  int res;
  int nStep;
  UnpackedRecord r;

  assert( pOp[1].opcode==OP_SeekGE );

  /* pOp->p2 points to the first instruction past the OP_IdxGT that
  ** follows the OP_SeekGE.  */
  assert( pOp->p2>=(int)(pOp-aOp)+2 );
  assert( aOp[pOp->p2-1].opcode==OP_IdxGT );
  assert( pOp[1].p1==aOp[pOp->p2-1].p1 );
  assert( pOp[1].p2==aOp[pOp->p2-1].p2 );
  assert( pOp[1].p3==aOp[pOp->p2-1].p3 );

  assert( pOp->p1>0 );
  pC = p->apCsr[pOp[1].p1];
  assert( pC!=0 );
  assert( pC->eCurType==CURTYPE_BTREE );
  assert( !pC->isTable );
  if( !sqlite3BtreeCursorIsValidNN(pC->uc.pCursor) ){
#ifdef SQLITE_DEBUG
     if( db->flags&SQLITE_VdbeTrace ){
       printf("... cursor not valid - fall through\n");
     }
#endif
    break;
  }
  nStep = pOp->p1;
  assert( nStep>=1 );
  r.pKeyInfo = pC->pKeyInfo;
  r.nField = (u16)pOp[1].p4.i;
  r.default_rc = 0;
  r.aMem = &aMem[pOp[1].p3];
#ifdef SQLITE_DEBUG
  {
    int i;
89934
89935
89936
89937
89938
89939
89940
89941
89942
89943
89944
89945
89946
89947
89948
89949
89950
89951
89952
89953
89954
89955
89956
89957
89958
89959
89960
89961
89962
89963
89964
89965
89966
89967
89968
89969
89970
89971
89972
89973
89974
  while(1){
    rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
    if( rc ) goto abort_due_to_error;
    if( res>0 ){
      seekscan_search_fail:
#ifdef SQLITE_DEBUG
      if( db->flags&SQLITE_VdbeTrace ){
        printf("... %d steps and then skip\n", pOp->p1 - n);
      }
#endif
      VdbeBranchTaken(1,3);
      pOp++;
      goto jump_to_p2;
    }
    if( res==0 ){
#ifdef SQLITE_DEBUG
      if( db->flags&SQLITE_VdbeTrace ){
        printf("... %d steps and then success\n", pOp->p1 - n);
      }
#endif
      VdbeBranchTaken(2,3);
      pOp += 2;
      break;
    }
    if( n<=0 ){
#ifdef SQLITE_DEBUG
      if( db->flags&SQLITE_VdbeTrace ){
        printf("... fall through after %d steps\n", pOp->p1);
      }
#endif
      VdbeBranchTaken(0,3);
      break;
    }
    n--;
    rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
    if( rc ){
      if( rc==SQLITE_DONE ){
        rc = SQLITE_OK;
        goto seekscan_search_fail;
      }else{
        goto abort_due_to_error;







|









|



|


|








|







89940
89941
89942
89943
89944
89945
89946
89947
89948
89949
89950
89951
89952
89953
89954
89955
89956
89957
89958
89959
89960
89961
89962
89963
89964
89965
89966
89967
89968
89969
89970
89971
89972
89973
89974
89975
89976
89977
89978
89979
89980
  while(1){
    rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
    if( rc ) goto abort_due_to_error;
    if( res>0 ){
      seekscan_search_fail:
#ifdef SQLITE_DEBUG
      if( db->flags&SQLITE_VdbeTrace ){
        printf("... %d steps and then skip\n", pOp->p1 - nStep);
      }
#endif
      VdbeBranchTaken(1,3);
      pOp++;
      goto jump_to_p2;
    }
    if( res==0 ){
#ifdef SQLITE_DEBUG
      if( db->flags&SQLITE_VdbeTrace ){
        printf("... %d steps and then success\n", pOp->p1 - nStep);
      }
#endif
      VdbeBranchTaken(2,3);
      goto jump_to_p2;
      break;
    }
    if( nStep<=0 ){
#ifdef SQLITE_DEBUG
      if( db->flags&SQLITE_VdbeTrace ){
        printf("... fall through after %d steps\n", pOp->p1);
      }
#endif
      VdbeBranchTaken(0,3);
      break;
    }
    nStep--;
    rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
    if( rc ){
      if( rc==SQLITE_DONE ){
        rc = SQLITE_OK;
        goto seekscan_search_fail;
      }else{
        goto abort_due_to_error;
100064
100065
100066
100067
100068
100069
100070
100071


100072
100073
100074
100075
100076
100077
100078
** SELECT * FROM t1 WHERE a;
** SELECT a AS b FROM t1 WHERE b;
** SELECT * FROM t1 WHERE (select a from t1);
*/
SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
  int op;
  while( ExprHasProperty(pExpr, EP_Skip|EP_IfNullRow) ){
    assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );


    pExpr = pExpr->pLeft;
    assert( pExpr!=0 );
  }
  op = pExpr->op;
  if( op==TK_SELECT ){
    assert( pExpr->flags&EP_xIsSelect );
    assert( pExpr->x.pSelect!=0 );







|
>
>







100070
100071
100072
100073
100074
100075
100076
100077
100078
100079
100080
100081
100082
100083
100084
100085
100086
** SELECT * FROM t1 WHERE a;
** SELECT a AS b FROM t1 WHERE b;
** SELECT * FROM t1 WHERE (select a from t1);
*/
SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
  int op;
  while( ExprHasProperty(pExpr, EP_Skip|EP_IfNullRow) ){
    assert( pExpr->op==TK_COLLATE
         || pExpr->op==TK_IF_NULL_ROW
         || (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) );
    pExpr = pExpr->pLeft;
    assert( pExpr!=0 );
  }
  op = pExpr->op;
  if( op==TK_SELECT ){
    assert( pExpr->flags&EP_xIsSelect );
    assert( pExpr->x.pSelect!=0 );
112358
112359
112360
112361
112362
112363
112364
112365
112366
112367
112368
112369
112370
112371
112372
*/
SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){
  Table *p;
  int i;
  char *zColl;              /* Dequoted name of collation sequence */
  sqlite3 *db;

  if( (p = pParse->pNewTable)==0 ) return;
  i = p->nCol-1;
  db = pParse->db;
  zColl = sqlite3NameFromToken(db, pToken);
  if( !zColl ) return;

  if( sqlite3LocateCollSeq(pParse, zColl) ){
    Index *pIdx;







|







112366
112367
112368
112369
112370
112371
112372
112373
112374
112375
112376
112377
112378
112379
112380
*/
SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){
  Table *p;
  int i;
  char *zColl;              /* Dequoted name of collation sequence */
  sqlite3 *db;

  if( (p = pParse->pNewTable)==0 || IN_RENAME_OBJECT ) return;
  i = p->nCol-1;
  db = pParse->db;
  zColl = sqlite3NameFromToken(db, pToken);
  if( !zColl ) return;

  if( sqlite3LocateCollSeq(pParse, zColl) ){
    Index *pIdx;
115359
115360
115361
115362
115363
115364
115365









115366
115367
115368
115369
115370
115371
115372
115373
  if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ){
    return;
  }
  v = sqlite3GetVdbe(pParse);
  if( !v ) return;
  if( type!=TK_DEFERRED ){
    for(i=0; i<db->nDb; i++){









      sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1);
      sqlite3VdbeUsesBtree(v, i);
    }
  }
  sqlite3VdbeAddOp0(v, OP_AutoCommit);
}

/*







>
>
>
>
>
>
>
>
>
|







115367
115368
115369
115370
115371
115372
115373
115374
115375
115376
115377
115378
115379
115380
115381
115382
115383
115384
115385
115386
115387
115388
115389
115390
  if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ){
    return;
  }
  v = sqlite3GetVdbe(pParse);
  if( !v ) return;
  if( type!=TK_DEFERRED ){
    for(i=0; i<db->nDb; i++){
      int eTxnType;
      Btree *pBt = db->aDb[i].pBt;
      if( pBt && sqlite3BtreeIsReadonly(pBt) ){
        eTxnType = 0;  /* Read txn */
      }else if( type==TK_EXCLUSIVE ){
        eTxnType = 2;  /* Exclusive txn */
      }else{
        eTxnType = 1;  /* Write txn */
      }
      sqlite3VdbeAddOp2(v, OP_Transaction, i, eTxnType);
      sqlite3VdbeUsesBtree(v, i);
    }
  }
  sqlite3VdbeAddOp0(v, OP_AutoCommit);
}

/*
117346
117347
117348
117349
117350
117351
117352
117353
117354
117355
117356
117357
117358
117359
117360
117361
117362
117363
    ** But we are getting ready to store this value back into an index, where
    ** it should be converted by to INTEGER again.  So omit the OP_RealAffinity
    ** opcode if it is present */
    sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
  }
  if( regOut ){
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
    if( pIdx->pTable->pSelect ){
      const char *zAff = sqlite3IndexAffinityStr(pParse->db, pIdx);
      sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
    }
  }
  sqlite3ReleaseTempRange(pParse, regBase, nCol);
  return regBase;
}

/*
** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label







<
<
<
<







117363
117364
117365
117366
117367
117368
117369




117370
117371
117372
117373
117374
117375
117376
    ** But we are getting ready to store this value back into an index, where
    ** it should be converted by to INTEGER again.  So omit the OP_RealAffinity
    ** opcode if it is present */
    sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
  }
  if( regOut ){
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);




  }
  sqlite3ReleaseTempRange(pParse, regBase, nCol);
  return regBase;
}

/*
** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label
138156
138157
138158
138159
138160
138161
138162
138163
138164
138165
138166
138167
138168
138169
138170
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
      if( pLimit ){
        pGrp = sqlite3ExprListAppend(pParse, pGrp, sqlite3ExprDup(db, pNew, 0));
      }
#endif
      pList = sqlite3ExprListAppend(pParse, pList, pNew);
    }
    eDest = SRT_Upfrom;
  }else if( pTab->pSelect ){
    for(i=0; i<pTab->nCol; i++){
      pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
    }
    eDest = SRT_Table;
  }else{
    eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;







|







138169
138170
138171
138172
138173
138174
138175
138176
138177
138178
138179
138180
138181
138182
138183
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
      if( pLimit ){
        pGrp = sqlite3ExprListAppend(pParse, pGrp, sqlite3ExprDup(db, pNew, 0));
      }
#endif
      pList = sqlite3ExprListAppend(pParse, pList, pNew);
    }
    eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
  }else if( pTab->pSelect ){
    for(i=0; i<pTab->nCol; i++){
      pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
    }
    eDest = SRT_Table;
  }else{
    eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
139109
139110
139111
139112
139113
139114
139115

139116
139117

139118
139119
139120
139121












139122
139123
139124
139125
139126
139127
139128
139129
139130
139131
139132
139133
139134
139135
139136
139137
139138
139139
139140
139141
139142
  ** these arguments will be temporarily stored. */
  assert( v );
  ephemTab = pParse->nTab++;
  addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg);
  regArg = pParse->nMem + 1;
  pParse->nMem += nArg;
  if( pSrc->nSrc>1 ){

    Expr *pRow;
    ExprList *pList;

    if( pRowid ){
      pRow = sqlite3ExprDup(db, pRowid, 0);
    }else{
      pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);












    }
    pList = sqlite3ExprListAppend(pParse, 0, pRow);

    for(i=0; i<pTab->nCol; i++){
      if( aXRef[i]>=0 ){
        pList = sqlite3ExprListAppend(pParse, pList,
          sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0)
        );
      }else{
        pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
      }
    }

    updateFromSelect(pParse, ephemTab, 0, pList, pSrc, pWhere, 0, 0);
    sqlite3ExprListDelete(db, pList);
    eOnePass = ONEPASS_OFF;
  }else{
    regRec = ++pParse->nMem;
    regRowid = ++pParse->nMem;

    /* Start scanning the virtual table */







>


>
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>













|







139122
139123
139124
139125
139126
139127
139128
139129
139130
139131
139132
139133
139134
139135
139136
139137
139138
139139
139140
139141
139142
139143
139144
139145
139146
139147
139148
139149
139150
139151
139152
139153
139154
139155
139156
139157
139158
139159
139160
139161
139162
139163
139164
139165
139166
139167
139168
139169
  ** these arguments will be temporarily stored. */
  assert( v );
  ephemTab = pParse->nTab++;
  addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg);
  regArg = pParse->nMem + 1;
  pParse->nMem += nArg;
  if( pSrc->nSrc>1 ){
    Index *pPk = 0;
    Expr *pRow;
    ExprList *pList;
    if( HasRowid(pTab) ){
      if( pRowid ){
        pRow = sqlite3ExprDup(db, pRowid, 0);
      }else{
        pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);
      }
    }else{
      i16 iPk;      /* PRIMARY KEY column */
      pPk = sqlite3PrimaryKeyIndex(pTab);
      assert( pPk!=0 );
      assert( pPk->nKeyCol==1 );
      iPk = pPk->aiColumn[0];
      if( aXRef[iPk]>=0 ){
        pRow = sqlite3ExprDup(db, pChanges->a[aXRef[iPk]].pExpr, 0);
      }else{
        pRow = exprRowColumn(pParse, iPk);
      }
    }
    pList = sqlite3ExprListAppend(pParse, 0, pRow);

    for(i=0; i<pTab->nCol; i++){
      if( aXRef[i]>=0 ){
        pList = sqlite3ExprListAppend(pParse, pList,
          sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0)
        );
      }else{
        pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
      }
    }

    updateFromSelect(pParse, ephemTab, pPk, pList, pSrc, pWhere, 0, 0);
    sqlite3ExprListDelete(db, pList);
    eOnePass = ONEPASS_OFF;
  }else{
    regRec = ++pParse->nMem;
    regRowid = ++pParse->nMem;

    /* Start scanning the virtual table */
142455
142456
142457
142458
142459
142460
142461

142462




142463
142464
142465
142466
142467
142468
142469
            }
          }else{
            pIn->eEndLoopOp = OP_Noop;
          }
          pIn++;
        }
      }

      if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){




        sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
      }
    }else{
      pLevel->u.in.nIn = 0;
    }
    sqlite3DbFree(pParse->db, aiMap);
#endif







>
|
>
>
>
>







142482
142483
142484
142485
142486
142487
142488
142489
142490
142491
142492
142493
142494
142495
142496
142497
142498
142499
142500
142501
            }
          }else{
            pIn->eEndLoopOp = OP_Noop;
          }
          pIn++;
        }
      }
      testcase( iEq>0
                && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
                && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
      if( iEq>0
       && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
      ){
        sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
      }
    }else{
      pLevel->u.in.nIn = 0;
    }
    sqlite3DbFree(pParse->db, aiMap);
#endif
143505
143506
143507
143508
143509
143510
143511

143512
143513
143514
143515
143516
143517
143518
    int op;                      /* Instruction opcode */
    char *zStartAff;             /* Affinity for start of range constraint */
    char *zEndAff = 0;           /* Affinity for end of range constraint */
    u8 bSeekPastNull = 0;        /* True to seek past initial nulls */
    u8 bStopAtNull = 0;          /* Add condition to terminate at NULLs */
    int omitTable;               /* True if we use the index only */
    int regBignull = 0;          /* big-null flag register */


    pIdx = pLoop->u.btree.pIndex;
    iIdxCur = pLevel->iIdxCur;
    assert( nEq>=pLoop->nSkip );

    /* Find any inequality constraint terms for the start and end
    ** of the range.







>







143537
143538
143539
143540
143541
143542
143543
143544
143545
143546
143547
143548
143549
143550
143551
    int op;                      /* Instruction opcode */
    char *zStartAff;             /* Affinity for start of range constraint */
    char *zEndAff = 0;           /* Affinity for end of range constraint */
    u8 bSeekPastNull = 0;        /* True to seek past initial nulls */
    u8 bStopAtNull = 0;          /* Add condition to terminate at NULLs */
    int omitTable;               /* True if we use the index only */
    int regBignull = 0;          /* big-null flag register */
    int addrSeekScan = 0;        /* Opcode of the OP_SeekScan, if any */

    pIdx = pLoop->u.btree.pIndex;
    iIdxCur = pLevel->iIdxCur;
    assert( nEq>=pLoop->nSkip );

    /* Find any inequality constraint terms for the start and end
    ** of the range.
143650
143651
143652
143653
143654
143655
143656
143657
143658
143659
143660
143661
143662
143663
143664
143665
143666
143667

143668
143669
143670
143671
143672
143673
143674
143675
      if( regBignull ){
        sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull);
        VdbeComment((v, "NULL-scan pass ctr"));
      }

      op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
      assert( op!=0 );
      if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 ){
        assert( op==OP_SeekGE );
        assert( regBignull==0 );
        /* TUNING:  The OP_SeekScan opcode seeks to reduce the number
        ** of expensive seek operations by replacing a single seek with
        ** 1 or more step operations.  The question is, how many steps
        ** should we try before giving up and going with a seek.  The cost
        ** of a seek is proportional to the logarithm of the of the number
        ** of entries in the tree, so basing the number of steps to try
        ** on the estimated number of rows in the btree seems like a good
        ** guess. */

        sqlite3VdbeAddOp1(v, OP_SeekScan, (pIdx->aiRowLogEst[0]+9)/10);
        VdbeCoverage(v);
      }
      sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
      VdbeCoverage(v);
      VdbeCoverageIf(v, op==OP_Rewind);  testcase( op==OP_Rewind );
      VdbeCoverageIf(v, op==OP_Last);    testcase( op==OP_Last );
      VdbeCoverageIf(v, op==OP_SeekGT);  testcase( op==OP_SeekGT );







|
<









>
|







143683
143684
143685
143686
143687
143688
143689
143690

143691
143692
143693
143694
143695
143696
143697
143698
143699
143700
143701
143702
143703
143704
143705
143706
143707
143708
      if( regBignull ){
        sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull);
        VdbeComment((v, "NULL-scan pass ctr"));
      }

      op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
      assert( op!=0 );
      if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 && op==OP_SeekGE ){

        assert( regBignull==0 );
        /* TUNING:  The OP_SeekScan opcode seeks to reduce the number
        ** of expensive seek operations by replacing a single seek with
        ** 1 or more step operations.  The question is, how many steps
        ** should we try before giving up and going with a seek.  The cost
        ** of a seek is proportional to the logarithm of the of the number
        ** of entries in the tree, so basing the number of steps to try
        ** on the estimated number of rows in the btree seems like a good
        ** guess. */
        addrSeekScan = sqlite3VdbeAddOp1(v, OP_SeekScan,
                                         (pIdx->aiRowLogEst[0]+9)/10);
        VdbeCoverage(v);
      }
      sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
      VdbeCoverage(v);
      VdbeCoverageIf(v, op==OP_Rewind);  testcase( op==OP_Rewind );
      VdbeCoverageIf(v, op==OP_Last);    testcase( op==OP_Last );
      VdbeCoverageIf(v, op==OP_SeekGT);  testcase( op==OP_SeekGT );
143746
143747
143748
143749
143750
143751
143752

143753
143754
143755
143756
143757
143758
143759
      }
      op = aEndOp[bRev*2 + endEq];
      sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
      testcase( op==OP_IdxGT );  VdbeCoverageIf(v, op==OP_IdxGT );
      testcase( op==OP_IdxGE );  VdbeCoverageIf(v, op==OP_IdxGE );
      testcase( op==OP_IdxLT );  VdbeCoverageIf(v, op==OP_IdxLT );
      testcase( op==OP_IdxLE );  VdbeCoverageIf(v, op==OP_IdxLE );

    }
    if( regBignull ){
      /* During a NULL-scan, check to see if we have reached the end of
      ** the NULLs */
      assert( bSeekPastNull==!bStopAtNull );
      assert( bSeekPastNull+bStopAtNull==1 );
      assert( nConstraint+bSeekPastNull>0 );







>







143779
143780
143781
143782
143783
143784
143785
143786
143787
143788
143789
143790
143791
143792
143793
      }
      op = aEndOp[bRev*2 + endEq];
      sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
      testcase( op==OP_IdxGT );  VdbeCoverageIf(v, op==OP_IdxGT );
      testcase( op==OP_IdxGE );  VdbeCoverageIf(v, op==OP_IdxGE );
      testcase( op==OP_IdxLT );  VdbeCoverageIf(v, op==OP_IdxLT );
      testcase( op==OP_IdxLE );  VdbeCoverageIf(v, op==OP_IdxLE );
      if( addrSeekScan ) sqlite3VdbeJumpHere(v, addrSeekScan);
    }
    if( regBignull ){
      /* During a NULL-scan, check to see if we have reached the end of
      ** the NULLs */
      assert( bSeekPastNull==!bStopAtNull );
      assert( bSeekPastNull+bStopAtNull==1 );
      assert( nConstraint+bSeekPastNull>0 );
148482
148483
148484
148485
148486
148487
148488
148489
148490
148491
148492
148493
148494
148495
148496
148497
148498
148499
148500
148501
148502
148503
148504
148505
148506
148507
148508

148509
148510
148511
148512
148513
148514
148515
        for(i=0; i<pNew->nLTerm-1; i++){
          if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
        }
      }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
        /* "x IN (value, value, ...)" */
        nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
      }
      if( pProbe->hasStat1 ){
        LogEst M, logK, safetyMargin;
        /* Let:
        **   N = the total number of rows in the table
        **   K = the number of entries on the RHS of the IN operator
        **   M = the number of rows in the table that match terms to the
        **       to the left in the same index.  If the IN operator is on
        **       the left-most index column, M==N.
        **
        ** Given the definitions above, it is better to omit the IN operator
        ** from the index lookup and instead do a scan of the M elements,
        ** testing each scanned row against the IN operator separately, if:
        **
        **        M*log(K) < K*log(N)
        **
        ** Our estimates for M, K, and N might be inaccurate, so we build in
        ** a safety margin of 2 (LogEst: 10) that favors using the IN operator
        ** with the index, as using an index has better worst-case behavior.
        ** If we do not have real sqlite_stat1 data, always prefer to use
        ** the index.

        */
        M = pProbe->aiRowLogEst[saved_nEq];
        logK = estLog(nIn);
        safetyMargin = 10;  /* TUNING: extra weight for indexed IN */
        if( M + logK + safetyMargin < nIn + rLogSize ){
          WHERETRACE(0x40,
            ("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n",







|


















|
>







148516
148517
148518
148519
148520
148521
148522
148523
148524
148525
148526
148527
148528
148529
148530
148531
148532
148533
148534
148535
148536
148537
148538
148539
148540
148541
148542
148543
148544
148545
148546
148547
148548
148549
148550
        for(i=0; i<pNew->nLTerm-1; i++){
          if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
        }
      }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
        /* "x IN (value, value, ...)" */
        nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
      }
      if( pProbe->hasStat1 && rLogSize>=10 ){
        LogEst M, logK, safetyMargin;
        /* Let:
        **   N = the total number of rows in the table
        **   K = the number of entries on the RHS of the IN operator
        **   M = the number of rows in the table that match terms to the
        **       to the left in the same index.  If the IN operator is on
        **       the left-most index column, M==N.
        **
        ** Given the definitions above, it is better to omit the IN operator
        ** from the index lookup and instead do a scan of the M elements,
        ** testing each scanned row against the IN operator separately, if:
        **
        **        M*log(K) < K*log(N)
        **
        ** Our estimates for M, K, and N might be inaccurate, so we build in
        ** a safety margin of 2 (LogEst: 10) that favors using the IN operator
        ** with the index, as using an index has better worst-case behavior.
        ** If we do not have real sqlite_stat1 data, always prefer to use
        ** the index.  Do not bother with this optimization on very small
        ** tables (less than 2 rows) as it is pointless in that case.
        */
        M = pProbe->aiRowLogEst[saved_nEq];
        logK = estLog(nIn);
        safetyMargin = 10;  /* TUNING: extra weight for indexed IN */
        if( M + logK + safetyMargin < nIn + rLogSize ){
          WHERETRACE(0x40,
            ("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n",
209275
209276
209277
209278
209279
209280
209281

209282
209283
209284
209285
209286
209287
209288
209289
209290
209291
209292
209293
209294
209295
209296
209297
209298
209299
209300
209301
209302
209303
209304
209305
209306
209307
209308
209309
209310
209311
209312


209313
209314
209315
209316
209317
209318
209319
  char *zContentRowid;            /* "content_rowid=" option value */
  int bColumnsize;                /* "columnsize=" option value (dflt==1) */
  int eDetail;                    /* FTS5_DETAIL_XXX value */
  char *zContentExprlist;
  Fts5Tokenizer *pTok;
  fts5_tokenizer *pTokApi;
  int bLock;                      /* True when table is preparing statement */


  /* Values loaded from the %_config table */
  int iCookie;                    /* Incremented when %_config is modified */
  int pgsz;                       /* Approximate page size used in %_data */
  int nAutomerge;                 /* 'automerge' setting */
  int nCrisisMerge;               /* Maximum allowed segments per level */
  int nUsermerge;                 /* 'usermerge' setting */
  int nHashSize;                  /* Bytes of memory for in-memory hash */
  char *zRank;                    /* Name of rank function */
  char *zRankArgs;                /* Arguments to rank function */

  /* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
  char **pzErrmsg;

#ifdef SQLITE_DEBUG
  int bPrefixIndex;               /* True to use prefix-indexes */
#endif
};

/* Current expected value of %_config table 'version' field */
#define FTS5_CURRENT_VERSION 4

#define FTS5_CONTENT_NORMAL   0
#define FTS5_CONTENT_NONE     1
#define FTS5_CONTENT_EXTERNAL 2

#define FTS5_DETAIL_FULL    0
#define FTS5_DETAIL_NONE    1
#define FTS5_DETAIL_COLUMNS 2





static int sqlite3Fts5ConfigParse(
    Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char**
);
static void sqlite3Fts5ConfigFree(Fts5Config*);

static int sqlite3Fts5ConfigDeclareVtab(Fts5Config *pConfig);







>




















|





|
|
|

|
>
>







209310
209311
209312
209313
209314
209315
209316
209317
209318
209319
209320
209321
209322
209323
209324
209325
209326
209327
209328
209329
209330
209331
209332
209333
209334
209335
209336
209337
209338
209339
209340
209341
209342
209343
209344
209345
209346
209347
209348
209349
209350
209351
209352
209353
209354
209355
209356
209357
  char *zContentRowid;            /* "content_rowid=" option value */
  int bColumnsize;                /* "columnsize=" option value (dflt==1) */
  int eDetail;                    /* FTS5_DETAIL_XXX value */
  char *zContentExprlist;
  Fts5Tokenizer *pTok;
  fts5_tokenizer *pTokApi;
  int bLock;                      /* True when table is preparing statement */
  int ePattern;                   /* FTS_PATTERN_XXX constant */

  /* Values loaded from the %_config table */
  int iCookie;                    /* Incremented when %_config is modified */
  int pgsz;                       /* Approximate page size used in %_data */
  int nAutomerge;                 /* 'automerge' setting */
  int nCrisisMerge;               /* Maximum allowed segments per level */
  int nUsermerge;                 /* 'usermerge' setting */
  int nHashSize;                  /* Bytes of memory for in-memory hash */
  char *zRank;                    /* Name of rank function */
  char *zRankArgs;                /* Arguments to rank function */

  /* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
  char **pzErrmsg;

#ifdef SQLITE_DEBUG
  int bPrefixIndex;               /* True to use prefix-indexes */
#endif
};

/* Current expected value of %_config table 'version' field */
#define FTS5_CURRENT_VERSION  4

#define FTS5_CONTENT_NORMAL   0
#define FTS5_CONTENT_NONE     1
#define FTS5_CONTENT_EXTERNAL 2

#define FTS5_DETAIL_FULL      0
#define FTS5_DETAIL_NONE      1
#define FTS5_DETAIL_COLUMNS   2

#define FTS5_PATTERN_NONE     0
#define FTS5_PATTERN_LIKE     65  /* matches SQLITE_INDEX_CONSTRAINT_LIKE */
#define FTS5_PATTERN_GLOB     66  /* matches SQLITE_INDEX_CONSTRAINT_GLOB */

static int sqlite3Fts5ConfigParse(
    Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char**
);
static void sqlite3Fts5ConfigFree(Fts5Config*);

static int sqlite3Fts5ConfigDeclareVtab(Fts5Config *pConfig);
209645
209646
209647
209648
209649
209650
209651
209652
209653
209654
209655
209656
209657
209658
209659
209660
  Fts5Index *pIndex;              /* Full-text index */
};

static int sqlite3Fts5GetTokenizer(
  Fts5Global*,
  const char **azArg,
  int nArg,
  Fts5Tokenizer**,
  fts5_tokenizer**,
  char **pzErr
);

static Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);

static int sqlite3Fts5FlushToDisk(Fts5Table*);








|
<







209683
209684
209685
209686
209687
209688
209689
209690

209691
209692
209693
209694
209695
209696
209697
  Fts5Index *pIndex;              /* Full-text index */
};

static int sqlite3Fts5GetTokenizer(
  Fts5Global*,
  const char **azArg,
  int nArg,
  Fts5Config*,

  char **pzErr
);

static Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);

static int sqlite3Fts5FlushToDisk(Fts5Table*);

209775
209776
209777
209778
209779
209780
209781

209782
209783
209784
209785







209786
209787
209788
209789
209790
209791
209792
  const char *p;                  /* Token text (not NULL terminated) */
  int n;                          /* Size of buffer p in bytes */
};

/* Parse a MATCH expression. */
static int sqlite3Fts5ExprNew(
  Fts5Config *pConfig,

  int iCol,                       /* Column on LHS of MATCH operator */
  const char *zExpr,
  Fts5Expr **ppNew,
  char **pzErr







);

/*
** for(rc = sqlite3Fts5ExprFirst(pExpr, pIdx, bDesc);
**     rc==SQLITE_OK && 0==sqlite3Fts5ExprEof(pExpr);
**     rc = sqlite3Fts5ExprNext(pExpr)
** ){







>




>
>
>
>
>
>
>







209812
209813
209814
209815
209816
209817
209818
209819
209820
209821
209822
209823
209824
209825
209826
209827
209828
209829
209830
209831
209832
209833
209834
209835
209836
209837
  const char *p;                  /* Token text (not NULL terminated) */
  int n;                          /* Size of buffer p in bytes */
};

/* Parse a MATCH expression. */
static int sqlite3Fts5ExprNew(
  Fts5Config *pConfig,
  int bPhraseToAnd,
  int iCol,                       /* Column on LHS of MATCH operator */
  const char *zExpr,
  Fts5Expr **ppNew,
  char **pzErr
);
static int sqlite3Fts5ExprPattern(
  Fts5Config *pConfig,
  int bGlob,
  int iCol,
  const char *zText,
  Fts5Expr **pp
);

/*
** for(rc = sqlite3Fts5ExprFirst(pExpr, pIdx, bDesc);
**     rc==SQLITE_OK && 0==sqlite3Fts5ExprEof(pExpr);
**     rc = sqlite3Fts5ExprNext(pExpr)
** ){
209888
209889
209890
209891
209892
209893
209894




209895
209896
209897
209898
209899
209900
209901
**************************************************************************/

/**************************************************************************
** Interface to code in fts5_tokenizer.c.
*/

static int sqlite3Fts5TokenizerInit(fts5_api*);




/*
** End of interface to code in fts5_tokenizer.c.
**************************************************************************/

/**************************************************************************
** Interface to code in fts5_vocab.c.
*/







>
>
>
>







209933
209934
209935
209936
209937
209938
209939
209940
209941
209942
209943
209944
209945
209946
209947
209948
209949
209950
**************************************************************************/

/**************************************************************************
** Interface to code in fts5_tokenizer.c.
*/

static int sqlite3Fts5TokenizerInit(fts5_api*);
static int sqlite3Fts5TokenizerPattern(
    int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
    Fts5Tokenizer *pTok
);
/*
** End of interface to code in fts5_tokenizer.c.
**************************************************************************/

/**************************************************************************
** Interface to code in fts5_vocab.c.
*/
212867
212868
212869
212870
212871
212872
212873
212874
212875
212876
212877
212878
212879
212880
212881
          }
        }
        if( p==0 ){
          *pzErr = sqlite3_mprintf("parse error in tokenize directive");
          rc = SQLITE_ERROR;
        }else{
          rc = sqlite3Fts5GetTokenizer(pGlobal,
              (const char**)azArg, (int)nArg, &pConfig->pTok, &pConfig->pTokApi,
              pzErr
          );
        }
      }
    }

    sqlite3_free(azArg);







|







212916
212917
212918
212919
212920
212921
212922
212923
212924
212925
212926
212927
212928
212929
212930
          }
        }
        if( p==0 ){
          *pzErr = sqlite3_mprintf("parse error in tokenize directive");
          rc = SQLITE_ERROR;
        }else{
          rc = sqlite3Fts5GetTokenizer(pGlobal,
              (const char**)azArg, (int)nArg, pConfig,
              pzErr
          );
        }
      }
    }

    sqlite3_free(azArg);
212939
212940
212941
212942
212943
212944
212945
212946
212947
212948
212949
212950
212951
212952
212953
212954
212955
/*
** Allocate an instance of the default tokenizer ("simple") at
** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
** code if an error occurs.
*/
static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
  assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
  return sqlite3Fts5GetTokenizer(
      pGlobal, 0, 0, &pConfig->pTok, &pConfig->pTokApi, 0
  );
}

/*
** Gobble up the first bareword or quoted word from the input buffer zIn.
** Return a pointer to the character immediately following the last in
** the gobbled word if successful, or a NULL pointer otherwise (failed
** to find close-quote character).







|
<
<







212988
212989
212990
212991
212992
212993
212994
212995


212996
212997
212998
212999
213000
213001
213002
/*
** Allocate an instance of the default tokenizer ("simple") at
** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
** code if an error occurs.
*/
static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
  assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
  return sqlite3Fts5GetTokenizer(pGlobal, 0, 0, pConfig, 0);


}

/*
** Gobble up the first bareword or quoted word from the input buffer zIn.
** Return a pointer to the character immediately following the last in
** the gobbled word if successful, or a NULL pointer otherwise (failed
** to find close-quote character).
213633
213634
213635
213636
213637
213638
213639

213640
213641
213642
213643
213644
213645
213646
struct Fts5Parse {
  Fts5Config *pConfig;
  char *zErr;
  int rc;
  int nPhrase;                    /* Size of apPhrase array */
  Fts5ExprPhrase **apPhrase;      /* Array of all phrases */
  Fts5ExprNode *pExpr;            /* Result of a successful parse */

};

static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
  va_list ap;
  va_start(ap, zFmt);
  if( pParse->rc==SQLITE_OK ){
    pParse->zErr = sqlite3_vmprintf(zFmt, ap);







>







213680
213681
213682
213683
213684
213685
213686
213687
213688
213689
213690
213691
213692
213693
213694
struct Fts5Parse {
  Fts5Config *pConfig;
  char *zErr;
  int rc;
  int nPhrase;                    /* Size of apPhrase array */
  Fts5ExprPhrase **apPhrase;      /* Array of all phrases */
  Fts5ExprNode *pExpr;            /* Result of a successful parse */
  int bPhraseToAnd;               /* Convert "a+b" to "a AND b" */
};

static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
  va_list ap;
  va_start(ap, zFmt);
  if( pParse->rc==SQLITE_OK ){
    pParse->zErr = sqlite3_vmprintf(zFmt, ap);
213721
213722
213723
213724
213725
213726
213727

213728
213729
213730
213731
213732
213733
213734
213735
213736
213737
213738
213739
213740
213741
213742

213743
213744
213745
213746
213747
213748
213749
}

static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc64((sqlite3_int64)t);}
static void fts5ParseFree(void *p){ sqlite3_free(p); }

static int sqlite3Fts5ExprNew(
  Fts5Config *pConfig,            /* FTS5 Configuration */

  int iCol,
  const char *zExpr,              /* Expression text */
  Fts5Expr **ppNew,
  char **pzErr
){
  Fts5Parse sParse;
  Fts5Token token;
  const char *z = zExpr;
  int t;                          /* Next token type */
  void *pEngine;
  Fts5Expr *pNew;

  *ppNew = 0;
  *pzErr = 0;
  memset(&sParse, 0, sizeof(sParse));

  pEngine = sqlite3Fts5ParserAlloc(fts5ParseAlloc);
  if( pEngine==0 ){ return SQLITE_NOMEM; }
  sParse.pConfig = pConfig;

  do {
    t = fts5ExprGetToken(&sParse, &z, &token);
    sqlite3Fts5Parser(pEngine, t, token, &sParse);







>















>







213769
213770
213771
213772
213773
213774
213775
213776
213777
213778
213779
213780
213781
213782
213783
213784
213785
213786
213787
213788
213789
213790
213791
213792
213793
213794
213795
213796
213797
213798
213799
}

static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc64((sqlite3_int64)t);}
static void fts5ParseFree(void *p){ sqlite3_free(p); }

static int sqlite3Fts5ExprNew(
  Fts5Config *pConfig,            /* FTS5 Configuration */
  int bPhraseToAnd,
  int iCol,
  const char *zExpr,              /* Expression text */
  Fts5Expr **ppNew,
  char **pzErr
){
  Fts5Parse sParse;
  Fts5Token token;
  const char *z = zExpr;
  int t;                          /* Next token type */
  void *pEngine;
  Fts5Expr *pNew;

  *ppNew = 0;
  *pzErr = 0;
  memset(&sParse, 0, sizeof(sParse));
  sParse.bPhraseToAnd = bPhraseToAnd;
  pEngine = sqlite3Fts5ParserAlloc(fts5ParseAlloc);
  if( pEngine==0 ){ return SQLITE_NOMEM; }
  sParse.pConfig = pConfig;

  do {
    t = fts5ExprGetToken(&sParse, &z, &token);
    sqlite3Fts5Parser(pEngine, t, token, &sParse);
213778
213779
213780
213781
213782
213783
213784

213785
213786
213787
213788
213789
213790
213791
213792
213793
213794











































































213795
213796
213797
213798
213799
213800
213801
      }else{
        pNew->pRoot = sParse.pExpr;
      }
      pNew->pIndex = 0;
      pNew->pConfig = pConfig;
      pNew->apExprPhrase = sParse.apPhrase;
      pNew->nPhrase = sParse.nPhrase;

      sParse.apPhrase = 0;
    }
  }else{
    sqlite3Fts5ParseNodeFree(sParse.pExpr);
  }

  sqlite3_free(sParse.apPhrase);
  *pzErr = sParse.zErr;
  return sParse.rc;
}












































































/*
** Free the expression node object passed as the only argument.
*/
static void sqlite3Fts5ParseNodeFree(Fts5ExprNode *p){
  if( p ){
    int i;







>










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







213828
213829
213830
213831
213832
213833
213834
213835
213836
213837
213838
213839
213840
213841
213842
213843
213844
213845
213846
213847
213848
213849
213850
213851
213852
213853
213854
213855
213856
213857
213858
213859
213860
213861
213862
213863
213864
213865
213866
213867
213868
213869
213870
213871
213872
213873
213874
213875
213876
213877
213878
213879
213880
213881
213882
213883
213884
213885
213886
213887
213888
213889
213890
213891
213892
213893
213894
213895
213896
213897
213898
213899
213900
213901
213902
213903
213904
213905
213906
213907
213908
213909
213910
213911
213912
213913
213914
213915
213916
213917
213918
213919
213920
213921
213922
213923
213924
213925
213926
213927
      }else{
        pNew->pRoot = sParse.pExpr;
      }
      pNew->pIndex = 0;
      pNew->pConfig = pConfig;
      pNew->apExprPhrase = sParse.apPhrase;
      pNew->nPhrase = sParse.nPhrase;
      pNew->bDesc = 0;
      sParse.apPhrase = 0;
    }
  }else{
    sqlite3Fts5ParseNodeFree(sParse.pExpr);
  }

  sqlite3_free(sParse.apPhrase);
  *pzErr = sParse.zErr;
  return sParse.rc;
}

/*
** This function is only called when using the special 'trigram' tokenizer.
** Argument zText contains the text of a LIKE or GLOB pattern matched
** against column iCol. This function creates and compiles an FTS5 MATCH
** expression that will match a superset of the rows matched by the LIKE or
** GLOB. If successful, SQLITE_OK is returned. Otherwise, an SQLite error
** code.
*/
static int sqlite3Fts5ExprPattern(
  Fts5Config *pConfig, int bGlob, int iCol, const char *zText, Fts5Expr **pp
){
  i64 nText = strlen(zText);
  char *zExpr = (char*)sqlite3_malloc64(nText*4 + 1);
  int rc = SQLITE_OK;

  if( zExpr==0 ){
    rc = SQLITE_NOMEM;
  }else{
    char aSpec[3];
    int iOut = 0;
    int i = 0;
    int iFirst = 0;

    if( bGlob==0 ){
      aSpec[0] = '_';
      aSpec[1] = '%';
      aSpec[2] = 0;
    }else{
      aSpec[0] = '*';
      aSpec[1] = '?';
      aSpec[2] = '[';
    }

    while( i<=nText ){
      if( i==nText
       || zText[i]==aSpec[0] || zText[i]==aSpec[1] || zText[i]==aSpec[2]
      ){
        if( i-iFirst>=3 ){
          int jj;
          zExpr[iOut++] = '"';
          for(jj=iFirst; jj<i; jj++){
            zExpr[iOut++] = zText[jj];
            if( zText[jj]=='"' ) zExpr[iOut++] = '"';
          }
          zExpr[iOut++] = '"';
          zExpr[iOut++] = ' ';
        }
        if( zText[i]==aSpec[2] ){
          i += 2;
          if( zText[i-1]=='^' ) i++;
          while( i<nText && zText[i]!=']' ) i++;
        }
        iFirst = i+1;
      }
      i++;
    }
    if( iOut>0 ){
      int bAnd = 0;
      if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
        bAnd = 1;
        if( pConfig->eDetail==FTS5_DETAIL_NONE ){
          iCol = pConfig->nCol;
        }
      }
      zExpr[iOut] = '\0';
      rc = sqlite3Fts5ExprNew(pConfig, bAnd, iCol, zExpr, pp,pConfig->pzErrmsg);
    }else{
      *pp = 0;
    }
    sqlite3_free(zExpr);
  }

  return rc;
}

/*
** Free the expression node object passed as the only argument.
*/
static void sqlite3Fts5ParseNodeFree(Fts5ExprNode *p){
  if( p ){
    int i;
215165
215166
215167
215168
215169
215170
215171














215172
215173
215174
215175
215176
215177
215178
  }
}

static void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p){
  assert( pParse->pExpr==0 );
  pParse->pExpr = p;
}















/*
** This function is called by the parser to process a string token. The
** string may or may not be quoted. In any case it is tokenized and a
** phrase object consisting of all tokens returned.
*/
static Fts5ExprPhrase *sqlite3Fts5ParseTerm(







>
>
>
>
>
>
>
>
>
>
>
>
>
>







215291
215292
215293
215294
215295
215296
215297
215298
215299
215300
215301
215302
215303
215304
215305
215306
215307
215308
215309
215310
215311
215312
215313
215314
215315
215316
215317
215318
  }
}

static void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p){
  assert( pParse->pExpr==0 );
  pParse->pExpr = p;
}

static int parseGrowPhraseArray(Fts5Parse *pParse){
  if( (pParse->nPhrase % 8)==0 ){
    sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
    Fts5ExprPhrase **apNew;
    apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
    if( apNew==0 ){
      pParse->rc = SQLITE_NOMEM;
      return SQLITE_NOMEM;
    }
    pParse->apPhrase = apNew;
  }
  return SQLITE_OK;
}

/*
** This function is called by the parser to process a string token. The
** string may or may not be quoted. In any case it is tokenized and a
** phrase object consisting of all tokens returned.
*/
static Fts5ExprPhrase *sqlite3Fts5ParseTerm(
215201
215202
215203
215204
215205
215206
215207
215208
215209
215210
215211
215212
215213
215214
215215
215216
215217
215218
215219
215220
215221
215222
215223
215224
  if( rc || (rc = sCtx.rc) ){
    pParse->rc = rc;
    fts5ExprPhraseFree(sCtx.pPhrase);
    sCtx.pPhrase = 0;
  }else{

    if( pAppend==0 ){
      if( (pParse->nPhrase % 8)==0 ){
        sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
        Fts5ExprPhrase **apNew;
        apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
        if( apNew==0 ){
          pParse->rc = SQLITE_NOMEM;
          fts5ExprPhraseFree(sCtx.pPhrase);
          return 0;
        }
        pParse->apPhrase = apNew;
      }
      pParse->nPhrase++;
    }

    if( sCtx.pPhrase==0 ){
      /* This happens when parsing a token or quoted phrase that contains
      ** no token characters at all. (e.g ... MATCH '""'). */







<
<
|
<
<
<
|
|
<
<







215341
215342
215343
215344
215345
215346
215347


215348



215349
215350


215351
215352
215353
215354
215355
215356
215357
  if( rc || (rc = sCtx.rc) ){
    pParse->rc = rc;
    fts5ExprPhraseFree(sCtx.pPhrase);
    sCtx.pPhrase = 0;
  }else{

    if( pAppend==0 ){


      if( parseGrowPhraseArray(pParse) ){



        fts5ExprPhraseFree(sCtx.pPhrase);
        return 0;


      }
      pParse->nPhrase++;
    }

    if( sCtx.pPhrase==0 ){
      /* This happens when parsing a token or quoted phrase that contains
      ** no token characters at all. (e.g ... MATCH '""'). */
215616
215617
215618
215619
215620
215621
215622





























































215623
215624
215625
215626
215627
215628
215629
    memcpy(&p->apChild[p->nChild], pSub->apChild, nByte);
    p->nChild += pSub->nChild;
    sqlite3_free(pSub);
  }else{
    p->apChild[p->nChild++] = pSub;
  }
}






























































/*
** Allocate and return a new expression object. If anything goes wrong (i.e.
** OOM error), leave an error code in pParse and return NULL.
*/
static Fts5ExprNode *sqlite3Fts5ParseNode(
  Fts5Parse *pParse,              /* Parse context */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







215749
215750
215751
215752
215753
215754
215755
215756
215757
215758
215759
215760
215761
215762
215763
215764
215765
215766
215767
215768
215769
215770
215771
215772
215773
215774
215775
215776
215777
215778
215779
215780
215781
215782
215783
215784
215785
215786
215787
215788
215789
215790
215791
215792
215793
215794
215795
215796
215797
215798
215799
215800
215801
215802
215803
215804
215805
215806
215807
215808
215809
215810
215811
215812
215813
215814
215815
215816
215817
215818
215819
215820
215821
215822
215823
    memcpy(&p->apChild[p->nChild], pSub->apChild, nByte);
    p->nChild += pSub->nChild;
    sqlite3_free(pSub);
  }else{
    p->apChild[p->nChild++] = pSub;
  }
}

/*
** This function is used when parsing LIKE or GLOB patterns against
** trigram indexes that specify either detail=column or detail=none.
** It converts a phrase:
**
**     abc + def + ghi
**
** into an AND tree:
**
**     abc AND def AND ghi
*/
static Fts5ExprNode *fts5ParsePhraseToAnd(
  Fts5Parse *pParse,
  Fts5ExprNearset *pNear
){
  int nTerm = pNear->apPhrase[0]->nTerm;
  int ii;
  int nByte;
  Fts5ExprNode *pRet;

  assert( pNear->nPhrase==1 );
  assert( pParse->bPhraseToAnd );

  nByte = sizeof(Fts5ExprNode) + nTerm*sizeof(Fts5ExprNode*);
  pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
  if( pRet ){
    pRet->eType = FTS5_AND;
    pRet->nChild = nTerm;
    fts5ExprAssignXNext(pRet);
    pParse->nPhrase--;
    for(ii=0; ii<nTerm; ii++){
      Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
          &pParse->rc, sizeof(Fts5ExprPhrase)
      );
      if( pPhrase ){
        if( parseGrowPhraseArray(pParse) ){
          fts5ExprPhraseFree(pPhrase);
        }else{
          pParse->apPhrase[pParse->nPhrase++] = pPhrase;
          pPhrase->nTerm = 1;
          pPhrase->aTerm[0].zTerm = sqlite3Fts5Strndup(
              &pParse->rc, pNear->apPhrase[0]->aTerm[ii].zTerm, -1
          );
          pRet->apChild[ii] = sqlite3Fts5ParseNode(pParse, FTS5_STRING,
              0, 0, sqlite3Fts5ParseNearset(pParse, 0, pPhrase)
          );
        }
      }
    }

    if( pParse->rc ){
      sqlite3Fts5ParseNodeFree(pRet);
      pRet = 0;
    }else{
      sqlite3Fts5ParseNearsetFree(pNear);
    }
  }

  return pRet;
}

/*
** Allocate and return a new expression object. If anything goes wrong (i.e.
** OOM error), leave an error code in pParse and return NULL.
*/
static Fts5ExprNode *sqlite3Fts5ParseNode(
  Fts5Parse *pParse,              /* Parse context */
215641
215642
215643
215644
215645
215646
215647






215648
215649
215650
215651
215652
215653
215654
215655
215656
215657
215658
215659
215660
215661
215662
215663
215664
215665
215666
215667
215668
215669
215670
215671
215672
215673
215674
215675
215676
215677
215678
215679
215680
215681
215682
215683
215684
215685
215686
215687
215688
215689
215690
215691
215692

215693
215694
215695
215696
215697
215698
215699
    assert( (eType!=FTS5_STRING && !pNear)
         || (eType==FTS5_STRING && !pLeft && !pRight)
    );
    if( eType==FTS5_STRING && pNear==0 ) return 0;
    if( eType!=FTS5_STRING && pLeft==0 ) return pRight;
    if( eType!=FTS5_STRING && pRight==0 ) return pLeft;







    if( eType==FTS5_NOT ){
      nChild = 2;
    }else if( eType==FTS5_AND || eType==FTS5_OR ){
      nChild = 2;
      if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
      if( pRight->eType==eType ) nChild += pRight->nChild-1;
    }

    nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
    pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);

    if( pRet ){
      pRet->eType = eType;
      pRet->pNear = pNear;
      fts5ExprAssignXNext(pRet);
      if( eType==FTS5_STRING ){
        int iPhrase;
        for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
          pNear->apPhrase[iPhrase]->pNode = pRet;
          if( pNear->apPhrase[iPhrase]->nTerm==0 ){
            pRet->xNext = 0;
            pRet->eType = FTS5_EOF;
          }
        }

        if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
          Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
          if( pNear->nPhrase!=1
           || pPhrase->nTerm>1
           || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
          ){
            assert( pParse->rc==SQLITE_OK );
            pParse->rc = SQLITE_ERROR;
            assert( pParse->zErr==0 );
            pParse->zErr = sqlite3_mprintf(
                "fts5: %s queries are not supported (detail!=full)",
                pNear->nPhrase==1 ? "phrase": "NEAR"
                );
            sqlite3_free(pRet);
            pRet = 0;
          }
        }
      }else{
        fts5ExprAddChildren(pRet, pLeft);
        fts5ExprAddChildren(pRet, pRight);

      }
    }
  }

  if( pRet==0 ){
    assert( pParse->rc!=SQLITE_OK );
    sqlite3Fts5ParseNodeFree(pLeft);







>
>
>
>
>
>
|
|
|
|
|
|
|

|
|

|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>







215835
215836
215837
215838
215839
215840
215841
215842
215843
215844
215845
215846
215847
215848
215849
215850
215851
215852
215853
215854
215855
215856
215857
215858
215859
215860
215861
215862
215863
215864
215865
215866
215867
215868
215869
215870
215871
215872
215873
215874
215875
215876
215877
215878
215879
215880
215881
215882
215883
215884
215885
215886
215887
215888
215889
215890
215891
215892
215893
215894
215895
215896
215897
215898
215899
215900
    assert( (eType!=FTS5_STRING && !pNear)
         || (eType==FTS5_STRING && !pLeft && !pRight)
    );
    if( eType==FTS5_STRING && pNear==0 ) return 0;
    if( eType!=FTS5_STRING && pLeft==0 ) return pRight;
    if( eType!=FTS5_STRING && pRight==0 ) return pLeft;

    if( eType==FTS5_STRING
     && pParse->bPhraseToAnd
     && pNear->apPhrase[0]->nTerm>1
    ){
      pRet = fts5ParsePhraseToAnd(pParse, pNear);
    }else{
      if( eType==FTS5_NOT ){
        nChild = 2;
      }else if( eType==FTS5_AND || eType==FTS5_OR ){
        nChild = 2;
        if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
        if( pRight->eType==eType ) nChild += pRight->nChild-1;
      }

      nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
      pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);

      if( pRet ){
        pRet->eType = eType;
        pRet->pNear = pNear;
        fts5ExprAssignXNext(pRet);
        if( eType==FTS5_STRING ){
          int iPhrase;
          for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
            pNear->apPhrase[iPhrase]->pNode = pRet;
            if( pNear->apPhrase[iPhrase]->nTerm==0 ){
              pRet->xNext = 0;
              pRet->eType = FTS5_EOF;
            }
          }

          if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
            Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
            if( pNear->nPhrase!=1
                || pPhrase->nTerm>1
                || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
              ){
              assert( pParse->rc==SQLITE_OK );
              pParse->rc = SQLITE_ERROR;
              assert( pParse->zErr==0 );
              pParse->zErr = sqlite3_mprintf(
                  "fts5: %s queries are not supported (detail!=full)",
                  pNear->nPhrase==1 ? "phrase": "NEAR"
                  );
              sqlite3_free(pRet);
              pRet = 0;
            }
          }
        }else{
          fts5ExprAddChildren(pRet, pLeft);
          fts5ExprAddChildren(pRet, pRight);
        }
      }
    }
  }

  if( pRet==0 ){
    assert( pParse->rc!=SQLITE_OK );
    sqlite3Fts5ParseNodeFree(pLeft);
216039
216040
216041
216042
216043
216044
216045
216046
216047
216048
216049
216050
216051
216052
216053
  }

  zExpr = (const char*)sqlite3_value_text(apVal[0]);
  if( zExpr==0 ) zExpr = "";

  rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
  if( rc==SQLITE_OK ){
    rc = sqlite3Fts5ExprNew(pConfig, pConfig->nCol, zExpr, &pExpr, &zErr);
  }
  if( rc==SQLITE_OK ){
    char *zText;
    if( pExpr->pRoot->xNext==0 ){
      zText = sqlite3_mprintf("");
    }else if( bTcl ){
      zText = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pRoot);







|







216240
216241
216242
216243
216244
216245
216246
216247
216248
216249
216250
216251
216252
216253
216254
  }

  zExpr = (const char*)sqlite3_value_text(apVal[0]);
  if( zExpr==0 ) zExpr = "";

  rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
  if( rc==SQLITE_OK ){
    rc = sqlite3Fts5ExprNew(pConfig, 0, pConfig->nCol, zExpr, &pExpr, &zErr);
  }
  if( rc==SQLITE_OK ){
    char *zText;
    if( pExpr->pRoot->xNext==0 ){
      zText = sqlite3_mprintf("");
    }else if( bTcl ){
      zText = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pRoot);
216744
216745
216746
216747
216748
216749
216750

216751
216752
216753
216754
216755
216756
216757
216758
216759
  assert( (p->nAlloc - p->nData) >= (9 + 4 + 1 + 3 + 5) );

  pPtr = (u8*)p;

  /* If this is a new rowid, append the 4-byte size field for the previous
  ** entry, and the new rowid for this entry.  */
  if( iRowid!=p->iRowid ){

    fts5HashAddPoslistSize(pHash, p, 0);
    p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid);
    p->iRowid = iRowid;
    bNew = 1;
    p->iSzPoslist = p->nData;
    if( pHash->eDetail!=FTS5_DETAIL_NONE ){
      p->nData += 1;
      p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1);
      p->iPos = 0;







>

|







216945
216946
216947
216948
216949
216950
216951
216952
216953
216954
216955
216956
216957
216958
216959
216960
216961
  assert( (p->nAlloc - p->nData) >= (9 + 4 + 1 + 3 + 5) );

  pPtr = (u8*)p;

  /* If this is a new rowid, append the 4-byte size field for the previous
  ** entry, and the new rowid for this entry.  */
  if( iRowid!=p->iRowid ){
    u64 iDiff = (u64)iRowid - (u64)p->iRowid;
    fts5HashAddPoslistSize(pHash, p, 0);
    p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iDiff);
    p->iRowid = iRowid;
    bNew = 1;
    p->iSzPoslist = p->nData;
    if( pHash->eDetail!=FTS5_DETAIL_NONE ){
      p->nData += 1;
      p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1);
      p->iPos = 0;
218720
218721
218722
218723
218724
218725
218726
218727
218728
218729
218730
218731
218732
218733
218734
218735
218736
218737
218738
218739
218740
218741
218742
218743
218744
218745
218746
218747
218748
218749

  if( n>pIter->iEndofDoclist ){
    n = pIter->iEndofDoclist;
  }

  ASSERT_SZLEAF_OK(pIter->pLeaf);
  while( 1 ){
    i64 iDelta = 0;

    if( eDetail==FTS5_DETAIL_NONE ){
      /* todo */
      if( i<n && a[i]==0 ){
        i++;
        if( i<n && a[i]==0 ) i++;
      }
    }else{
      int nPos;
      int bDummy;
      i += fts5GetPoslistSize(&a[i], &nPos, &bDummy);
      i += nPos;
    }
    if( i>=n ) break;
    i += fts5GetVarint(&a[i], (u64*)&iDelta);
    pIter->iRowid += iDelta;

    /* If necessary, grow the pIter->aRowidOffset[] array. */
    if( iRowidOffset>=pIter->nRowidOffset ){
      int nNew = pIter->nRowidOffset + 8;
      int *aNew = (int*)sqlite3_realloc64(pIter->aRowidOffset,nNew*sizeof(int));
      if( aNew==0 ){







|














|







218922
218923
218924
218925
218926
218927
218928
218929
218930
218931
218932
218933
218934
218935
218936
218937
218938
218939
218940
218941
218942
218943
218944
218945
218946
218947
218948
218949
218950
218951

  if( n>pIter->iEndofDoclist ){
    n = pIter->iEndofDoclist;
  }

  ASSERT_SZLEAF_OK(pIter->pLeaf);
  while( 1 ){
    u64 iDelta = 0;

    if( eDetail==FTS5_DETAIL_NONE ){
      /* todo */
      if( i<n && a[i]==0 ){
        i++;
        if( i<n && a[i]==0 ) i++;
      }
    }else{
      int nPos;
      int bDummy;
      i += fts5GetPoslistSize(&a[i], &nPos, &bDummy);
      i += nPos;
    }
    if( i>=n ) break;
    i += fts5GetVarint(&a[i], &iDelta);
    pIter->iRowid += iDelta;

    /* If necessary, grow the pIter->aRowidOffset[] array. */
    if( iRowidOffset>=pIter->nRowidOffset ){
      int nNew = pIter->nRowidOffset + 8;
      int *aNew = (int*)sqlite3_realloc64(pIter->aRowidOffset,nNew*sizeof(int));
      if( aNew==0 ){
218834
218835
218836
218837
218838
218839
218840
218841
218842
218843
218844
218845
218846
218847
218848
218849
218850
218851
218852
218853
218854
218855
218856
218857
  assert( pIter->flags & FTS5_SEGITER_REVERSE );
  assert( pIter->pNextLeaf==0 );
  UNUSED_PARAM(pbUnused);

  if( pIter->iRowidOffset>0 ){
    u8 *a = pIter->pLeaf->p;
    int iOff;
    i64 iDelta;

    pIter->iRowidOffset--;
    pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset];
    fts5SegIterLoadNPos(p, pIter);
    iOff = pIter->iLeafOffset;
    if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){
      iOff += pIter->nPos;
    }
    fts5GetVarint(&a[iOff], (u64*)&iDelta);
    pIter->iRowid -= iDelta;
  }else{
    fts5SegIterReverseNewPage(p, pIter);
  }
}

/*







|








|







219036
219037
219038
219039
219040
219041
219042
219043
219044
219045
219046
219047
219048
219049
219050
219051
219052
219053
219054
219055
219056
219057
219058
219059
  assert( pIter->flags & FTS5_SEGITER_REVERSE );
  assert( pIter->pNextLeaf==0 );
  UNUSED_PARAM(pbUnused);

  if( pIter->iRowidOffset>0 ){
    u8 *a = pIter->pLeaf->p;
    int iOff;
    u64 iDelta;

    pIter->iRowidOffset--;
    pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset];
    fts5SegIterLoadNPos(p, pIter);
    iOff = pIter->iLeafOffset;
    if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){
      iOff += pIter->nPos;
    }
    fts5GetVarint(&a[iOff], &iDelta);
    pIter->iRowid -= iDelta;
  }else{
    fts5SegIterReverseNewPage(p, pIter);
  }
}

/*
224062
224063
224064
224065
224066
224067
224068

















224069
224070
224071
224072
224073
224074
224075
  if( sqlite3_libversion_number()>=3008012 )
#endif
  {
    pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
  }
#endif
}


















/*
** Implementation of the xBestIndex method for FTS5 tables. Within the
** WHERE constraint, it searches for the following:
**
**   1. A MATCH constraint against the table column.
**   2. A MATCH constraint against the "rank" column.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







224264
224265
224266
224267
224268
224269
224270
224271
224272
224273
224274
224275
224276
224277
224278
224279
224280
224281
224282
224283
224284
224285
224286
224287
224288
224289
224290
224291
224292
224293
224294
  if( sqlite3_libversion_number()>=3008012 )
#endif
  {
    pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
  }
#endif
}

static int fts5UsePatternMatch(
  Fts5Config *pConfig,
  struct sqlite3_index_constraint *p
){
  assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
  assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
  if( pConfig->ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
    return 1;
  }
  if( pConfig->ePattern==FTS5_PATTERN_LIKE
   && (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
  ){
    return 1;
  }
  return 0;
}

/*
** Implementation of the xBestIndex method for FTS5 tables. Within the
** WHERE constraint, it searches for the following:
**
**   1. A MATCH constraint against the table column.
**   2. A MATCH constraint against the "rank" column.
224092
224093
224094
224095
224096
224097
224098
224099


224100
224101
224102
224103
224104
224105
224106
**     FTS5_BI_ORDER_DESC
**
** idxStr is used to encode data from the WHERE clause. For each argument
** passed to the xFilter method, the following is appended to idxStr:
**
**   Match against table column:            "m"
**   Match against rank column:             "r"
**   Match against other column:            "<column-number>"


**   Equality constraint against the rowid: "="
**   A < or <= against the rowid:           "<"
**   A > or >= against the rowid:           ">"
**
** This function ensures that there is at most one "r" or "=". And that if
** there exists an "=" then there is no "<" or ">".
**







|
>
>







224311
224312
224313
224314
224315
224316
224317
224318
224319
224320
224321
224322
224323
224324
224325
224326
224327
**     FTS5_BI_ORDER_DESC
**
** idxStr is used to encode data from the WHERE clause. For each argument
** passed to the xFilter method, the following is appended to idxStr:
**
**   Match against table column:            "m"
**   Match against rank column:             "r"
**   Match against other column:            "M<column-number>"
**   LIKE  against other column:            "L<column-number>"
**   GLOB  against other column:            "G<column-number>"
**   Equality constraint against the rowid: "="
**   A < or <= against the rowid:           "<"
**   A > or >= against the rowid:           ">"
**
** This function ensures that there is at most one "r" or "=". And that if
** there exists an "=" then there is no "<" or ">".
**
224153
224154
224155
224156
224157
224158
224159
224160
224161
224162
224163
224164
224165
224166
224167
  if( pConfig->bLock ){
    pTab->base.zErrMsg = sqlite3_mprintf(
        "recursively defined fts5 content table"
    );
    return SQLITE_ERROR;
  }

  idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 6 + 1);
  if( idxStr==0 ) return SQLITE_NOMEM;
  pInfo->idxStr = idxStr;
  pInfo->needToFreeIdxStr = 1;

  for(i=0; i<pInfo->nConstraint; i++){
    struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
    int iCol = p->iColumn;







|







224374
224375
224376
224377
224378
224379
224380
224381
224382
224383
224384
224385
224386
224387
224388
  if( pConfig->bLock ){
    pTab->base.zErrMsg = sqlite3_mprintf(
        "recursively defined fts5 content table"
    );
    return SQLITE_ERROR;
  }

  idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 8 + 1);
  if( idxStr==0 ) return SQLITE_NOMEM;
  pInfo->idxStr = idxStr;
  pInfo->needToFreeIdxStr = 1;

  for(i=0; i<pInfo->nConstraint; i++){
    struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
    int iCol = p->iColumn;
224177
224178
224179
224180
224181
224182
224183
224184
224185
224186
224187
224188
224189
224190
224191
224192
224193
224194
224195
224196
224197







224198
224199
224200
224201
224202

224203
224204
224205
224206
224207
224208
224209
        idxStr[iIdxStr] = 0;
        return SQLITE_OK;
      }else{
        if( iCol==nCol+1 ){
          if( bSeenRank ) continue;
          idxStr[iIdxStr++] = 'r';
          bSeenRank = 1;
        }else{
          bSeenMatch = 1;
          idxStr[iIdxStr++] = 'm';
          if( iCol<nCol ){
            sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
            idxStr += strlen(&idxStr[iIdxStr]);
            assert( idxStr[iIdxStr]=='\0' );
          }
        }
        pInfo->aConstraintUsage[i].argvIndex = ++iCons;
        pInfo->aConstraintUsage[i].omit = 1;
      }
    }
    else if( p->usable && bSeenEq==0







      && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0
    ){
      idxStr[iIdxStr++] = '=';
      bSeenEq = 1;
      pInfo->aConstraintUsage[i].argvIndex = ++iCons;

    }
  }

  if( bSeenEq==0 ){
    for(i=0; i<pInfo->nConstraint; i++){
      struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
      if( p->iColumn<0 && p->usable ){







|

|
<
|
|
|
<




<
|
>
>
>
>
>
>
>
|
<
|
|
|
>







224398
224399
224400
224401
224402
224403
224404
224405
224406
224407

224408
224409
224410

224411
224412
224413
224414

224415
224416
224417
224418
224419
224420
224421
224422
224423

224424
224425
224426
224427
224428
224429
224430
224431
224432
224433
224434
        idxStr[iIdxStr] = 0;
        return SQLITE_OK;
      }else{
        if( iCol==nCol+1 ){
          if( bSeenRank ) continue;
          idxStr[iIdxStr++] = 'r';
          bSeenRank = 1;
        }else if( iCol>=0 ){
          bSeenMatch = 1;
          idxStr[iIdxStr++] = 'M';

          sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
          idxStr += strlen(&idxStr[iIdxStr]);
          assert( idxStr[iIdxStr]=='\0' );

        }
        pInfo->aConstraintUsage[i].argvIndex = ++iCons;
        pInfo->aConstraintUsage[i].omit = 1;
      }

    }else if( p->usable ){
      if( iCol>=0 && iCol<nCol && fts5UsePatternMatch(pConfig, p) ){
        assert( p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB );
        idxStr[iIdxStr++] = p->op==FTS5_PATTERN_LIKE ? 'L' : 'G';
        sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
        idxStr += strlen(&idxStr[iIdxStr]);
        pInfo->aConstraintUsage[i].argvIndex = ++iCons;
        assert( idxStr[iIdxStr]=='\0' );
      }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){

        idxStr[iIdxStr++] = '=';
        bSeenEq = 1;
        pInfo->aConstraintUsage[i].argvIndex = ++iCons;
      }
    }
  }

  if( bSeenEq==0 ){
    for(i=0; i<pInfo->nConstraint; i++){
      struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
      if( p->iColumn<0 && p->usable ){
224828
224829
224830
224831
224832
224833
224834
224835
224836
224837
224838
224839
224840
224841
224842
224843
224844
224845
224846
224847
224848
224849
224850
224851
224852
224853
224854
224855
224856
224857
224858
224859
224860
224861
224862
224863
224864
224865



















224866
224867
224868
224869
224870
224871
224872

  /* Decode the arguments passed through to this function. */
  for(i=0; i<nVal; i++){
    switch( idxStr[iIdxStr++] ){
      case 'r':
        pRank = apVal[i];
        break;
      case 'm': {
        const char *zText = (const char*)sqlite3_value_text(apVal[i]);
        if( zText==0 ) zText = "";

        if( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' ){
          iCol = 0;
          do{
            iCol = iCol*10 + (idxStr[iIdxStr]-'0');
            iIdxStr++;
          }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
        }else{
          iCol = pConfig->nCol;
        }

        if( zText[0]=='*' ){
          /* The user has issued a query of the form "MATCH '*...'". This
          ** indicates that the MATCH expression is not a full text query,
          ** but a request for an internal parameter.  */
          rc = fts5SpecialMatch(pTab, pCsr, &zText[1]);
          goto filter_out;
        }else{
          char **pzErr = &pTab->p.base.zErrMsg;
          rc = sqlite3Fts5ExprNew(pConfig, iCol, zText, &pExpr, pzErr);
          if( rc==SQLITE_OK ){
            rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
            pExpr = 0;
          }
          if( rc!=SQLITE_OK ) goto filter_out;
        }

        break;



















      }
      case '=':
        pRowidEq = apVal[i];
        break;
      case '<':
        pRowidLe = apVal[i];
        break;







|


<
<
|
|
|
|
|
<
<
<









|








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







225053
225054
225055
225056
225057
225058
225059
225060
225061
225062


225063
225064
225065
225066
225067



225068
225069
225070
225071
225072
225073
225074
225075
225076
225077
225078
225079
225080
225081
225082
225083
225084
225085
225086
225087
225088
225089
225090
225091
225092
225093
225094
225095
225096
225097
225098
225099
225100
225101
225102
225103
225104
225105
225106
225107
225108
225109
225110
225111

  /* Decode the arguments passed through to this function. */
  for(i=0; i<nVal; i++){
    switch( idxStr[iIdxStr++] ){
      case 'r':
        pRank = apVal[i];
        break;
      case 'M': {
        const char *zText = (const char*)sqlite3_value_text(apVal[i]);
        if( zText==0 ) zText = "";


        iCol = 0;
        do{
          iCol = iCol*10 + (idxStr[iIdxStr]-'0');
          iIdxStr++;
        }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );




        if( zText[0]=='*' ){
          /* The user has issued a query of the form "MATCH '*...'". This
          ** indicates that the MATCH expression is not a full text query,
          ** but a request for an internal parameter.  */
          rc = fts5SpecialMatch(pTab, pCsr, &zText[1]);
          goto filter_out;
        }else{
          char **pzErr = &pTab->p.base.zErrMsg;
          rc = sqlite3Fts5ExprNew(pConfig, 0, iCol, zText, &pExpr, pzErr);
          if( rc==SQLITE_OK ){
            rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
            pExpr = 0;
          }
          if( rc!=SQLITE_OK ) goto filter_out;
        }

        break;
      }
      case 'L':
      case 'G': {
        int bGlob = (idxStr[iIdxStr-1]=='G');
        const char *zText = (const char*)sqlite3_value_text(apVal[i]);
        iCol = 0;
        do{
          iCol = iCol*10 + (idxStr[iIdxStr]-'0');
          iIdxStr++;
        }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
        if( zText ){
          rc = sqlite3Fts5ExprPattern(pConfig, bGlob, iCol, zText, &pExpr);
        }
        if( rc==SQLITE_OK ){
          rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
          pExpr = 0;
        }
        if( rc!=SQLITE_OK ) goto filter_out;
        break;
      }
      case '=':
        pRowidEq = apVal[i];
        break;
      case '<':
        pRowidLe = apVal[i];
        break;
226271
226272
226273
226274
226275
226276
226277
226278
226279
226280
226281
226282
226283
226284
226285
226286
226287
226288
226289
226290

226291

226292
226293
226294




226295
226296
226297
226298
226299
226300
226301
226302
226303
226304
226305
226306
226307
  return rc;
}

static int sqlite3Fts5GetTokenizer(
  Fts5Global *pGlobal,
  const char **azArg,
  int nArg,
  Fts5Tokenizer **ppTok,
  fts5_tokenizer **ppTokApi,
  char **pzErr
){
  Fts5TokenizerModule *pMod;
  int rc = SQLITE_OK;

  pMod = fts5LocateTokenizer(pGlobal, nArg==0 ? 0 : azArg[0]);
  if( pMod==0 ){
    assert( nArg>0 );
    rc = SQLITE_ERROR;
    *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
  }else{

    rc = pMod->x.xCreate(pMod->pUserData, &azArg[1], (nArg?nArg-1:0), ppTok);

    *ppTokApi = &pMod->x;
    if( rc!=SQLITE_OK && pzErr ){
      *pzErr = sqlite3_mprintf("error in tokenizer constructor");




    }
  }

  if( rc!=SQLITE_OK ){
    *ppTokApi = 0;
    *ppTok = 0;
  }

  return rc;
}

static void fts5ModuleDestroy(void *pCtx){
  Fts5TokenizerModule *pTok, *pNextTok;







|
<











>
|
>
|
|
|
>
>
>
>




|
|







226510
226511
226512
226513
226514
226515
226516
226517

226518
226519
226520
226521
226522
226523
226524
226525
226526
226527
226528
226529
226530
226531
226532
226533
226534
226535
226536
226537
226538
226539
226540
226541
226542
226543
226544
226545
226546
226547
226548
226549
226550
226551
  return rc;
}

static int sqlite3Fts5GetTokenizer(
  Fts5Global *pGlobal,
  const char **azArg,
  int nArg,
  Fts5Config *pConfig,

  char **pzErr
){
  Fts5TokenizerModule *pMod;
  int rc = SQLITE_OK;

  pMod = fts5LocateTokenizer(pGlobal, nArg==0 ? 0 : azArg[0]);
  if( pMod==0 ){
    assert( nArg>0 );
    rc = SQLITE_ERROR;
    *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
  }else{
    rc = pMod->x.xCreate(
        pMod->pUserData, &azArg[1], (nArg?nArg-1:0), &pConfig->pTok
    );
    pConfig->pTokApi = &pMod->x;
    if( rc!=SQLITE_OK ){
      if( pzErr ) *pzErr = sqlite3_mprintf("error in tokenizer constructor");
    }else{
      pConfig->ePattern = sqlite3Fts5TokenizerPattern(
          pMod->x.xCreate, pConfig->pTok
      );
    }
  }

  if( rc!=SQLITE_OK ){
    pConfig->pTokApi = 0;
    pConfig->pTok = 0;
  }

  return rc;
}

static void fts5ModuleDestroy(void *pCtx){
  Fts5TokenizerModule *pTok, *pNextTok;
226342
226343
226344
226345
226346
226347
226348
226349
226350
226351
226352
226353
226354
226355
226356
static void fts5SourceIdFunc(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args */
  sqlite3_value **apUnused        /* Function arguments */
){
  assert( nArg==0 );
  UNUSED_PARAM2(nArg, apUnused);
  sqlite3_result_text(pCtx, "fts5: 2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c402e5", -1, SQLITE_TRANSIENT);
}

/*
** Return true if zName is the extension on one of the shadow tables used
** by this module.
*/
static int fts5ShadowName(const char *zName){







|







226586
226587
226588
226589
226590
226591
226592
226593
226594
226595
226596
226597
226598
226599
226600
static void fts5SourceIdFunc(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args */
  sqlite3_value **apUnused        /* Function arguments */
){
  assert( nArg==0 );
  UNUSED_PARAM2(nArg, apUnused);
  sqlite3_result_text(pCtx, "fts5: 2020-10-12 18:09:16 7e17c2f4b7dc9b563d0b4da949bb134dc7c4fc9c86ce03891432a884ca6409d5", -1, SQLITE_TRANSIENT);
}

/*
** Return true if zName is the extension on one of the shadow tables used
** by this module.
*/
static int fts5ShadowName(const char *zName){
228895
228896
228897
228898
228899
228900
228901





























































































































228902
228903
228904
228905
228906
228907
228908
228909
228910
228911
228912
228913

228914
228915
228916
228917
228918
228919
228920
  sCtx.xToken = xToken;
  sCtx.pCtx = pCtx;
  sCtx.aBuf = p->aBuf;
  return p->tokenizer.xTokenize(
      p->pTokenizer, (void*)&sCtx, flags, pText, nText, fts5PorterCb
  );
}






























































































































/*
** Register all built-in tokenizers with FTS5.
*/
static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
  struct BuiltinTokenizer {
    const char *zName;
    fts5_tokenizer x;
  } aBuiltin[] = {
    { "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}},
    { "ascii",     {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }},
    { "porter",    {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }},

  };

  int rc = SQLITE_OK;             /* Return code */
  int i;                          /* To iterate through builtin functions */

  for(i=0; rc==SQLITE_OK && i<ArraySize(aBuiltin); i++){
    rc = pApi->xCreateTokenizer(pApi,







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












>







229139
229140
229141
229142
229143
229144
229145
229146
229147
229148
229149
229150
229151
229152
229153
229154
229155
229156
229157
229158
229159
229160
229161
229162
229163
229164
229165
229166
229167
229168
229169
229170
229171
229172
229173
229174
229175
229176
229177
229178
229179
229180
229181
229182
229183
229184
229185
229186
229187
229188
229189
229190
229191
229192
229193
229194
229195
229196
229197
229198
229199
229200
229201
229202
229203
229204
229205
229206
229207
229208
229209
229210
229211
229212
229213
229214
229215
229216
229217
229218
229219
229220
229221
229222
229223
229224
229225
229226
229227
229228
229229
229230
229231
229232
229233
229234
229235
229236
229237
229238
229239
229240
229241
229242
229243
229244
229245
229246
229247
229248
229249
229250
229251
229252
229253
229254
229255
229256
229257
229258
229259
229260
229261
229262
229263
229264
229265
229266
229267
229268
229269
229270
229271
229272
229273
229274
229275
229276
229277
229278
229279
229280
229281
229282
229283
229284
229285
229286
229287
229288
229289
229290
  sCtx.xToken = xToken;
  sCtx.pCtx = pCtx;
  sCtx.aBuf = p->aBuf;
  return p->tokenizer.xTokenize(
      p->pTokenizer, (void*)&sCtx, flags, pText, nText, fts5PorterCb
  );
}

/**************************************************************************
** Start of trigram implementation.
*/
typedef struct TrigramTokenizer TrigramTokenizer;
struct TrigramTokenizer {
  int bFold;                      /* True to fold to lower-case */
};

/*
** Free a trigram tokenizer.
*/
static void fts5TriDelete(Fts5Tokenizer *p){
  sqlite3_free(p);
}

/*
** Allocate a trigram tokenizer.
*/
static int fts5TriCreate(
  void *pCtx,
  const char **azArg,
  int nArg,
  Fts5Tokenizer **ppOut
){
  int rc = SQLITE_OK;
  TrigramTokenizer *pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
  if( pNew==0 ){
    rc = SQLITE_NOMEM;
  }else{
    int i;
    pNew->bFold = 1;
    for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
      const char *zArg = azArg[i+1];
      if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
        if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
          rc = SQLITE_ERROR;
        }else{
          pNew->bFold = (zArg[0]=='0');
        }
      }else{
        rc = SQLITE_ERROR;
      }
    }
    if( rc!=SQLITE_OK ){
      fts5TriDelete((Fts5Tokenizer*)pNew);
      pNew = 0;
    }
  }
  *ppOut = (Fts5Tokenizer*)pNew;
  return rc;
}

/*
** Trigram tokenizer tokenize routine.
*/
static int fts5TriTokenize(
  Fts5Tokenizer *pTok,
  void *pCtx,
  int flags,
  const char *pText, int nText,
  int (*xToken)(void*, int, const char*, int, int, int)
){
  TrigramTokenizer *p = (TrigramTokenizer*)pTok;
  int rc = SQLITE_OK;
  char aBuf[32];
  const unsigned char *zIn = (const unsigned char*)pText;
  const unsigned char *zEof = &zIn[nText];
  u32 iCode;

  while( 1 ){
    char *zOut = aBuf;
    int iStart = zIn - (const unsigned char*)pText;
    const unsigned char *zNext;

    READ_UTF8(zIn, zEof, iCode);
    if( iCode==0 ) break;
    zNext = zIn;
    if( zIn<zEof ){
      if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
      WRITE_UTF8(zOut, iCode);
      READ_UTF8(zIn, zEof, iCode);
      if( iCode==0 ) break;
    }else{
      break;
    }
    if( zIn<zEof ){
      if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
      WRITE_UTF8(zOut, iCode);
      READ_UTF8(zIn, zEof, iCode);
      if( iCode==0 ) break;
      if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
      WRITE_UTF8(zOut, iCode);
    }else{
      break;
    }
    rc = xToken(pCtx, 0, aBuf, zOut-aBuf, iStart, iStart + zOut-aBuf);
    if( rc!=SQLITE_OK ) break;
    zIn = zNext;
  }

  return rc;
}

/*
** Argument xCreate is a pointer to a constructor function for a tokenizer.
** pTok is a tokenizer previously created using the same method. This function
** returns one of FTS5_PATTERN_NONE, FTS5_PATTERN_LIKE or FTS5_PATTERN_GLOB
** indicating the style of pattern matching that the tokenizer can support.
** In practice, this is:
**
**     "trigram" tokenizer, case_sensitive=1 - FTS5_PATTERN_GLOB
**     "trigram" tokenizer, case_sensitive=0 (the default) - FTS5_PATTERN_LIKE
**     all other tokenizers - FTS5_PATTERN_NONE
*/
static int sqlite3Fts5TokenizerPattern(
    int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
    Fts5Tokenizer *pTok
){
  if( xCreate==fts5TriCreate ){
    TrigramTokenizer *p = (TrigramTokenizer*)pTok;
    return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB;
  }
  return FTS5_PATTERN_NONE;
}

/*
** Register all built-in tokenizers with FTS5.
*/
static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
  struct BuiltinTokenizer {
    const char *zName;
    fts5_tokenizer x;
  } aBuiltin[] = {
    { "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}},
    { "ascii",     {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }},
    { "porter",    {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }},
    { "trigram",   {fts5TriCreate, fts5TriDelete, fts5TriTokenize}},
  };

  int rc = SQLITE_OK;             /* Return code */
  int i;                          /* To iterate through builtin functions */

  for(i=0; rc==SQLITE_OK && i<ArraySize(aBuiltin); i++){
    rc = pApi->xCreateTokenizer(pApi,
231138
231139
231140
231141
231142
231143
231144
231145
231146
231147
231148
231149
231150
231151
#endif
  return rc;
}
#endif /* SQLITE_CORE */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */

/************** End of stmt.c ************************************************/
#if __LINE__!=231145
#undef SQLITE_SOURCE_ID
#define SQLITE_SOURCE_ID      "2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c4alt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
/************************** End of sqlite3.c ******************************/







|

|




231508
231509
231510
231511
231512
231513
231514
231515
231516
231517
231518
231519
231520
231521
#endif
  return rc;
}
#endif /* SQLITE_CORE */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */

/************** End of stmt.c ************************************************/
#if __LINE__!=231515
#undef SQLITE_SOURCE_ID
#define SQLITE_SOURCE_ID      "2020-10-12 18:09:16 7e17c2f4b7dc9b563d0b4da949bb134dc7c4fc9c86ce03891432a884ca64alt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
/************************** End of sqlite3.c ******************************/
Changes to src/sqlite3.h.
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.34.0"
#define SQLITE_VERSION_NUMBER 3034000
#define SQLITE_SOURCE_ID      "2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c402e5"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros







|







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.34.0"
#define SQLITE_VERSION_NUMBER 3034000
#define SQLITE_SOURCE_ID      "2020-10-12 18:09:16 7e17c2f4b7dc9b563d0b4da949bb134dc7c4fc9c86ce03891432a884ca6409d5"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros