SQLite4
Check-in [697ee9faad]
Not logged in

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

Overview
Comment:Inserting NULL into a INTEGER PRIMARY KEY fills that key with the next available integer value. The sqlite4_last_insert_rowid() function now works for those cases.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 697ee9faad4ac65ccc47cbda439d1791e2d7021d
User & Date: drh 2013-01-19 16:14:47
Context
2013-01-19
19:49
Insert a value in place of NULL in an INTEGER PRIMARY KEY, even if the IPK column is omitted from the VALUES list in the INSERT statement. check-in: 4d1b506594 user: drh tags: trunk
16:14
Inserting NULL into a INTEGER PRIMARY KEY fills that key with the next available integer value. The sqlite4_last_insert_rowid() function now works for those cases. check-in: 697ee9faad user: drh tags: trunk
02:38
Change the hexadecimal digits generated by the hex() and quote() functions to lower-case. check-in: 3025370e1f user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
....
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089



1090
1091




1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
....
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
....
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
....
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
** Designate the PRIMARY KEY for the table.  pList is a list of names 
** of columns that form the primary key.  If pList is NULL, then the
** most recently added column of the table is the primary key.
**
** A table can have at most one primary key.  If the table already has
** a primary key (and this is the second primary key) then create an
** error.
**
** If the PRIMARY KEY is on a single column whose datatype is INTEGER,
** then we will try to use that column as the rowid.  Set the Table.iPKey
** field of the table under construction to be the index of the
** INTEGER PRIMARY KEY column.  Table.iPKey is set to -1 if there is
** no INTEGER PRIMARY KEY.
**
** If the key is not an INTEGER PRIMARY KEY, then create a unique
** index for the key.  No index is created for INTEGER PRIMARY KEYs.
*/
void sqlite4AddPrimaryKey(
  Parse *pParse,    /* Parsing context */
  ExprList *pList,  /* List of field names to be indexed */
  int onError,      /* What to do with a uniqueness conflict */
  int autoInc,      /* True if the AUTOINCREMENT keyword is present */
  int sortOrder     /* SQLITE4_SO_ASC or SQLITE4_SO_DESC */
){
  Table *pTab = pParse->pNewTable;
#if 0
  char *zType = 0;
#endif
  int iCol = -1, i;
  if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit;
  if( pTab->tabFlags & TF_HasPrimaryKey ){
    sqlite4ErrorMsg(pParse, 
      "table \"%s\" has more than one primary key", pTab->zName);
    goto primary_key_exit;
  }
................................................................................
    for(i=0; i<pList->nExpr; i++){
      for(iCol=0; iCol<pTab->nCol; iCol++){
        if( sqlite4StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){
          break;
        }
      }
      if( iCol<pTab->nCol ){
        pTab->aCol[iCol].isPrimKey = 1;
        pTab->aCol[iCol].notNull = 1;
      }
    }
    if( pList->nExpr>1 ) iCol = -1;
  }




#if 0




  if( iCol>=0 && iCol<pTab->nCol ){
    zType = pTab->aCol[iCol].zType;
  }

  if( zType && sqlite4StrICmp(zType, "INTEGER")==0
        && sortOrder==SQLITE4_SO_ASC ){
    pTab->iPKey = iCol;
    pTab->keyConf = (u8)onError;
    assert( autoInc==0 || autoInc==1 );
    pTab->tabFlags |= autoInc*TF_Autoincrement;
  }else if( autoInc ){
#ifndef SQLITE4_OMIT_AUTOINCREMENT

    sqlite4ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
       "INTEGER PRIMARY KEY");
#endif
  }else
#endif

  {
    sqlite4CreateIndex(
        pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0, 1
    );
    pList = 0;
  }

primary_key_exit:
  sqlite4ExprListDelete(pParse->db, pList);
  return;
}

/*
................................................................................
  /* If pName==0 it means that we are dealing with a primary key or 
  ** UNIQUE constraint.  We have to invent our own name.  */
  if( pName==0 ){
    if( !bPrimaryKey ){
      int n;
      Index *pLoop;
      for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
      zName = sqlite4MPrintf(db, "sqlite_autoindex_%s_%d", pTab->zName, n);
    }else{
      zName = sqlite4MPrintf(db, "%s", pTab->zName);
    }
    if( zName==0 ){
      goto exit_create_index;
    }
  }
................................................................................

  /* Scan the names of the columns of the table to be indexed and
  ** load the column indices into the Index structure.  Report an error
  ** if any column is not found.
  **
  ** TODO:  Add a test to make sure that the same column is not named
  ** more than once within the same index.  Only the first instance of
  ** the column will ever be used by the optimizer.  Note that using the
  ** same column more than once cannot be an error because that would 
  ** break backwards compatibility - it needs to be a warning.
  */
  for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
    const char *zColName = pListItem->zName;
    Column *pTabCol;
    char *zColl;                   /* Collation sequence name */

    for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
................................................................................
    if( j>=pTab->nCol ){
      sqlite4ErrorMsg(pParse, "table %s has no column named %s",
        pTab->zName, zColName);
      pParse->checkSchema = 1;
      goto exit_create_index;
    }
    pIndex->aiColumn[i] = j;
    /* Justification of the ALWAYS(pListItem->pExpr->pColl):  Because of
    ** the way the "idxlist" non-terminal is constructed by the parser,
    ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl
    ** must exist or else there must have been an OOM error.  But if there
    ** was an OOM error, we would never reach this point. */
    if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){
      int nColl;
      zColl = pListItem->pExpr->pColl->zName;
      nColl = sqlite4Strlen30(zColl) + 1;
      assert( nExtra>=nColl );
      memcpy(zExtra, zColl, nColl);
      zColl = zExtra;
      zExtra += nColl;







<
<
<
<
<
<
<
<
<









|
|
<







 







|





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







 







|







 







|
<
<







 







<
<
<
<
<
|







1036
1037
1038
1039
1040
1041
1042









1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053

1054
1055
1056
1057
1058
1059
1060
....
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083

1084
1085
1086
1087
1088
1089


1090
1091




1092

1093
1094




1095




1096

1097
1098
1099
1100
1101
1102
1103
....
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
....
2715
2716
2717
2718
2719
2720
2721
2722


2723
2724
2725
2726
2727
2728
2729
....
2732
2733
2734
2735
2736
2737
2738





2739
2740
2741
2742
2743
2744
2745
2746
** Designate the PRIMARY KEY for the table.  pList is a list of names 
** of columns that form the primary key.  If pList is NULL, then the
** most recently added column of the table is the primary key.
**
** A table can have at most one primary key.  If the table already has
** a primary key (and this is the second primary key) then create an
** error.









*/
void sqlite4AddPrimaryKey(
  Parse *pParse,    /* Parsing context */
  ExprList *pList,  /* List of field names to be indexed */
  int onError,      /* What to do with a uniqueness conflict */
  int autoInc,      /* True if the AUTOINCREMENT keyword is present */
  int sortOrder     /* SQLITE4_SO_ASC or SQLITE4_SO_DESC */
){
  Table *pTab = pParse->pNewTable;
  Index *pPk;                        /* Primary key index */
  char *zType = 0;                   /* Primary key column type */

  int iCol = -1, i;
  if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit;
  if( pTab->tabFlags & TF_HasPrimaryKey ){
    sqlite4ErrorMsg(pParse, 
      "table \"%s\" has more than one primary key", pTab->zName);
    goto primary_key_exit;
  }
................................................................................
    for(i=0; i<pList->nExpr; i++){
      for(iCol=0; iCol<pTab->nCol; iCol++){
        if( sqlite4StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){
          break;
        }
      }
      if( iCol<pTab->nCol ){
        pTab->aCol[iCol].isPrimKey = i+1;
        pTab->aCol[iCol].notNull = 1;
      }
    }
    if( pList->nExpr>1 ) iCol = -1;
  }
  if( autoInc ){
    sqlite4ErrorMsg(pParse, "AUTOINCREMENT not yet implemented");
    goto primary_key_exit;
  }

  pPk = sqlite4CreateIndex(
     pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0, 1
  );

  if( iCol>=0 && iCol<pTab->nCol
   && (zType = pTab->aCol[iCol].zType)!=0


   && sqlite4StrICmp(zType, "INTEGER")==0
   && sortOrder==SQLITE4_SO_ASC




   && pPk

  ){
    pPk->fIndex |= IDX_IntPK;




  }




  pList = 0;


primary_key_exit:
  sqlite4ExprListDelete(pParse->db, pList);
  return;
}

/*
................................................................................
  /* If pName==0 it means that we are dealing with a primary key or 
  ** UNIQUE constraint.  We have to invent our own name.  */
  if( pName==0 ){
    if( !bPrimaryKey ){
      int n;
      Index *pLoop;
      for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
      zName = sqlite4MPrintf(db, "sqlite_%s_unique%d", pTab->zName, n);
    }else{
      zName = sqlite4MPrintf(db, "%s", pTab->zName);
    }
    if( zName==0 ){
      goto exit_create_index;
    }
  }
................................................................................

  /* Scan the names of the columns of the table to be indexed and
  ** load the column indices into the Index structure.  Report an error
  ** if any column is not found.
  **
  ** TODO:  Add a test to make sure that the same column is not named
  ** more than once within the same index.  Only the first instance of
  ** the column will ever be used by the optimizer.


  */
  for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
    const char *zColName = pListItem->zName;
    Column *pTabCol;
    char *zColl;                   /* Collation sequence name */

    for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
................................................................................
    if( j>=pTab->nCol ){
      sqlite4ErrorMsg(pParse, "table %s has no column named %s",
        pTab->zName, zColName);
      pParse->checkSchema = 1;
      goto exit_create_index;
    }
    pIndex->aiColumn[i] = j;





    if( pListItem->pExpr && pListItem->pExpr->pColl ){
      int nColl;
      zColl = pListItem->pExpr->pColl->zName;
      nColl = sqlite4Strlen30(zColl) + 1;
      assert( nExtra>=nColl );
      memcpy(zExtra, zColl, nColl);
      zColl = zExtra;
      zExtra += nColl;

Changes to src/delete.c.

549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
      sqlite4VdbeAddOp3(v, OP_Column, iPkCsr, pPk->aiColumn[i], regVal);
    }
  }

  /* Build the index key. If bAddSeq is true, append a sequence number to 
  ** the end of the key to ensure it is unique.  */
  sqlite4VdbeAddOp3(v, OP_MakeIdxKey, iIdxCsr, regTmp, regOut);
  if( bAddSeq ) sqlite4VdbeChangeP5(v, 1);

  /* Release temp registers */
  sqlite4ReleaseTempRange(pParse, regTmp, nTmpReg);
}

/*
** This routine generates VDBE code that causes the deletion of all







|







549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
      sqlite4VdbeAddOp3(v, OP_Column, iPkCsr, pPk->aiColumn[i], regVal);
    }
  }

  /* Build the index key. If bAddSeq is true, append a sequence number to 
  ** the end of the key to ensure it is unique.  */
  sqlite4VdbeAddOp3(v, OP_MakeIdxKey, iIdxCsr, regTmp, regOut);
  if( bAddSeq ) sqlite4VdbeChangeP5(v, OPFLAG_SEQCOUNT);

  /* Release temp registers */
  sqlite4ReleaseTempRange(pParse, regTmp, nTmpReg);
}

/*
** This routine generates VDBE code that causes the deletion of all

Changes to src/insert.c.

521
522
523
524
525
526
527

528
529
530
531
532
533
534
...
560
561
562
563
564
565
566







567


568
569
570
571
572
573
574
...
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
...
863
864
865
866
867
868
869






870
871
872
873
874
875
876
....
1058
1059
1060
1061
1062
1063
1064



1065
1066
1067
1068
1069
1070
1071
....
1287
1288
1289
1290
1291
1292
1293



1294
1295
1296
1297
1298
1299
1300
  /* Register allocations */
  int regFromSelect = 0;/* Base register for data coming from SELECT */
  int regEof = 0;       /* Register recording end of SELECT data */
  int *aRegIdx = 0;     /* One register allocated to each index */

  int iPk;                        /* Cursor offset of PK index cursor */
  Index *pPk;                     /* Primary key for table pTab */

  int bImplicitPK;                /* True if table pTab has an implicit PK */
  int regContent;                 /* First register in column value array */
  int regRowid;                   /* If bImplicitPK, register holding IPK */


#ifndef SQLITE4_OMIT_TRIGGER
  int isView;                 /* True if attempting to insert into a view */
................................................................................

  /* Set bImplicitPK to true for an implicit PRIMARY KEY, or false otherwise.
  ** Also set pPk to point to the primary key, and iPk to the cursor offset
  ** of the primary key cursor (i.e. so that the cursor opened on the primary
  ** key index is VDBE cursor (baseCur+iPk).  */
  pPk = sqlite4FindPrimaryKey(pTab, &iPk);
  assert( (pPk==0)==IsView(pTab) );







  bImplicitPK = (pPk && pPk->aiColumn[0]==-1);



  /* Figure out if we have any triggers and if the table being
  ** inserted into is a view. */
#ifndef SQLITE4_OMIT_TRIGGER
  pTrigger = sqlite4TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask);
  isView = pTab->pSelect!=0;
#else
................................................................................
    */
    addrCont = sqlite4VdbeAddOp1(v, OP_Yield, dest.iParm);
    addrInsTop = sqlite4VdbeAddOp1(v, OP_If, regEof);
  }

  /* Allocate an array of registers in which to assemble the values for the
  ** new row. If the table has an explicit primary key, we need one register
  ** for each table column. If the table uses an implicit primary key, the
  ** nCol+1 registers are required.  */
  regRowid = ++pParse->nMem;
  regContent = pParse->nMem+1;
  pParse->nMem += pTab->nCol;

  if( IsVirtual(pTab) ){
    /* TODO: Fix this */
................................................................................
      sqlite4VdbeAddOp3(v, OP_Column, srcTab, j, regContent+i);
    }else if( pSelect ){
      sqlite4VdbeAddOp2(v, OP_SCopy, regFromSelect+j, regContent+i);
    }else{
      assert( pSelect==0 ); /* Otherwise useTempTable is true */
      sqlite4ExprCodeAndCache(pParse, pList->a[j].pExpr, regContent+i);
    }






  }

  if( !isView ){
    sqlite4VdbeAddOp2(v, OP_Affinity, regContent, pTab->nCol);
    sqlite4TableAffinityStr(v, pTab);
  }

................................................................................
    sqlite4VdbeResolveLabel(v, allOk);
  }
}
#else /* !defined(SQLITE4_OMIT_CHECK) */
# define generateCheckChecks(a,b,c,d,e)
#endif




Index *sqlite4FindPrimaryKey(
  Table *pTab,                    /* Table to locate primary key for */
  int *piPk                       /* OUT: Index of PRIMARY KEY */
){
  Index *p;
  int iPk = 0;
  for(p=pTab->pIndex; p && p->eIndexType!=SQLITE4_INDEX_PRIMARYKEY; p=p->pNext){
................................................................................
    if( pIdx!=pPk ){
      for(i=0; i<pPk->nColumn; i++){
        int idx = pPk->aiColumn[i];
        sqlite4VdbeAddOp2(v, OP_SCopy, regContent+idx, regTmp+i+pIdx->nColumn);
      }
    }
    sqlite4VdbeAddOp3(v, OP_MakeIdxKey, iIdx, regTmp, regKey);



    VdbeComment((v, "key for %s", pIdx->zName));

    /* If Index.onError==OE_None, then pIdx is not a UNIQUE or PRIMARY KEY 
    ** index. In this case there is no need to test the index for uniqueness
    ** - all that is required is to populate the regKey register. Jump 
    ** to the next iteration of the loop if this is the case.  */
    onError = pIdx->onError;







>







 







>
>
>
>
>
>
>
|
>
>







 







|







 







>
>
>
>
>
>







 







>
>
>







 







>
>
>







521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
...
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
...
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
...
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
....
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
....
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
  /* Register allocations */
  int regFromSelect = 0;/* Base register for data coming from SELECT */
  int regEof = 0;       /* Register recording end of SELECT data */
  int *aRegIdx = 0;     /* One register allocated to each index */

  int iPk;                        /* Cursor offset of PK index cursor */
  Index *pPk;                     /* Primary key for table pTab */
  int iIntPKCol = -1;             /* Column of INTEGER PRIMARY KEY or -1 */
  int bImplicitPK;                /* True if table pTab has an implicit PK */
  int regContent;                 /* First register in column value array */
  int regRowid;                   /* If bImplicitPK, register holding IPK */


#ifndef SQLITE4_OMIT_TRIGGER
  int isView;                 /* True if attempting to insert into a view */
................................................................................

  /* Set bImplicitPK to true for an implicit PRIMARY KEY, or false otherwise.
  ** Also set pPk to point to the primary key, and iPk to the cursor offset
  ** of the primary key cursor (i.e. so that the cursor opened on the primary
  ** key index is VDBE cursor (baseCur+iPk).  */
  pPk = sqlite4FindPrimaryKey(pTab, &iPk);
  assert( (pPk==0)==IsView(pTab) );
  if( pPk ){
    bImplicitPK = pPk->aiColumn[0]==(-1);
    if( pPk->fIndex & IDX_IntPK ){
      assert( pPk->nColumn==1 );
      iIntPKCol = pPk->aiColumn[0];
    }
  }else{
    bImplicitPK = 0;
  }
      

  /* Figure out if we have any triggers and if the table being
  ** inserted into is a view. */
#ifndef SQLITE4_OMIT_TRIGGER
  pTrigger = sqlite4TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask);
  isView = pTab->pSelect!=0;
#else
................................................................................
    */
    addrCont = sqlite4VdbeAddOp1(v, OP_Yield, dest.iParm);
    addrInsTop = sqlite4VdbeAddOp1(v, OP_If, regEof);
  }

  /* Allocate an array of registers in which to assemble the values for the
  ** new row. If the table has an explicit primary key, we need one register
  ** for each table column. If the table uses an implicit primary key, then
  ** nCol+1 registers are required.  */
  regRowid = ++pParse->nMem;
  regContent = pParse->nMem+1;
  pParse->nMem += pTab->nCol;

  if( IsVirtual(pTab) ){
    /* TODO: Fix this */
................................................................................
      sqlite4VdbeAddOp3(v, OP_Column, srcTab, j, regContent+i);
    }else if( pSelect ){
      sqlite4VdbeAddOp2(v, OP_SCopy, regFromSelect+j, regContent+i);
    }else{
      assert( pSelect==0 ); /* Otherwise useTempTable is true */
      sqlite4ExprCodeAndCache(pParse, pList->a[j].pExpr, regContent+i);
    }
    if( j==iIntPKCol ){
      int a1;
      a1 = sqlite4VdbeAddOp1(v, OP_NotNull, regContent+i);
      sqlite4VdbeAddOp2(v, OP_NewRowid, baseCur, regContent+i);
      sqlite4VdbeJumpHere(v, a1);
    }
  }

  if( !isView ){
    sqlite4VdbeAddOp2(v, OP_Affinity, regContent, pTab->nCol);
    sqlite4TableAffinityStr(v, pTab);
  }

................................................................................
    sqlite4VdbeResolveLabel(v, allOk);
  }
}
#else /* !defined(SQLITE4_OMIT_CHECK) */
# define generateCheckChecks(a,b,c,d,e)
#endif

/*
** Locate the primary key index for a table.
*/
Index *sqlite4FindPrimaryKey(
  Table *pTab,                    /* Table to locate primary key for */
  int *piPk                       /* OUT: Index of PRIMARY KEY */
){
  Index *p;
  int iPk = 0;
  for(p=pTab->pIndex; p && p->eIndexType!=SQLITE4_INDEX_PRIMARYKEY; p=p->pNext){
................................................................................
    if( pIdx!=pPk ){
      for(i=0; i<pPk->nColumn; i++){
        int idx = pPk->aiColumn[i];
        sqlite4VdbeAddOp2(v, OP_SCopy, regContent+idx, regTmp+i+pIdx->nColumn);
      }
    }
    sqlite4VdbeAddOp3(v, OP_MakeIdxKey, iIdx, regTmp, regKey);
    if( pIdx==pPk && (pPk->fIndex & IDX_IntPK)!=0 ){
      sqlite4VdbeChangeP5(v, OPFLAG_LASTROWID);
    }
    VdbeComment((v, "key for %s", pIdx->zName));

    /* If Index.onError==OE_None, then pIdx is not a UNIQUE or PRIMARY KEY 
    ** index. In this case there is no need to test the index for uniqueness
    ** - all that is required is to populate the regKey register. Jump 
    ** to the next iteration of the loop if this is the case.  */
    onError = pIdx->onError;

Changes to src/select.c.

4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
        ** of the expressions in the GROUP BY list followed by a sequence
        ** number (to ensure each key is unique - the point of this is just
        ** to sort the rows, not to eliminate duplicates).  */
        sqlite4ExprCacheClear(pParse);
        regBase = sqlite4GetTempRange(pParse, nGroup);
        sqlite4ExprCodeExprList(pParse, pGroupBy, regBase, 0);
        sqlite4VdbeAddOp3(v, OP_MakeIdxKey, sAggInfo.sortingIdx,regBase,regKey);
        sqlite4VdbeChangeP5(v, 1);
        sqlite4ReleaseTempRange(pParse, regBase, nGroup);

        /* Encode the record for the sorting index. The record contains all
        ** required column values from the elements of the FROM clause.  
        ** If no column values are required, insert a NULL into the sorting
        ** index instead of a record. No column values are required for 
        ** queries such as "SELECT count(*) FROM ..."  */







|







4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
        ** of the expressions in the GROUP BY list followed by a sequence
        ** number (to ensure each key is unique - the point of this is just
        ** to sort the rows, not to eliminate duplicates).  */
        sqlite4ExprCacheClear(pParse);
        regBase = sqlite4GetTempRange(pParse, nGroup);
        sqlite4ExprCodeExprList(pParse, pGroupBy, regBase, 0);
        sqlite4VdbeAddOp3(v, OP_MakeIdxKey, sAggInfo.sortingIdx,regBase,regKey);
        sqlite4VdbeChangeP5(v, OPFLAG_SEQCOUNT);
        sqlite4ReleaseTempRange(pParse, regBase, nGroup);

        /* Encode the record for the sorting index. The record contains all
        ** required column values from the elements of the FROM clause.  
        ** If no column values are required, insert a NULL into the sorting
        ** index instead of a record. No column values are required for 
        ** queries such as "SELECT count(*) FROM ..."  */

Changes to src/sqlite.h.in.

740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
#define SQLITE4_DBCONFIG_ENABLE_FKEY     1002  /* int int* */
#define SQLITE4_DBCONFIG_ENABLE_TRIGGER  1003  /* int int* */


/*
** CAPIREF: Last Insert Rowid
**
** ^Each entry in an SQLite table has a unique 64-bit signed
** integer key called the [ROWID | "rowid"]. ^The rowid is always available
** as an undeclared column named ROWID, OID, or _ROWID_ as long as those
** names are not also used by explicitly declared columns. ^If
** the table has a column of type [INTEGER PRIMARY KEY] then that column
** is another alias for the rowid.
**
** ^This routine returns the [rowid] of the most recent
** successful [INSERT] into the database from the [database connection]
** in the first argument.  ^As of SQLite version 3.7.7, this routines
** records the last insert rowid of both ordinary tables and [virtual tables].
** ^If no successful [INSERT]s
** have ever occurred on that database connection, zero is returned.
**
** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
** method, then this routine will return the [rowid] of the inserted
** row as long as the trigger or virtual table method is running.
** But once the trigger or virtual table method ends, the value returned 
** by this routine reverts to what it was before the trigger or virtual
** table method began.)^







|
|
|
|
|
|
|
<
<
<
<
<
<







740
741
742
743
744
745
746
747
748
749
750
751
752
753






754
755
756
757
758
759
760
#define SQLITE4_DBCONFIG_ENABLE_FKEY     1002  /* int int* */
#define SQLITE4_DBCONFIG_ENABLE_TRIGGER  1003  /* int int* */


/*
** CAPIREF: Last Insert Rowid
**
** ^The sqlite4_last_insert_rowid(D) routine returns the primary key value
** of the the most recent successful [INSERT] from [database connection] D
** into a table where the primary key of the inserted row is a single
** integer.
** ^If there have been no successful [INSERT]s of rows with a single integer
** PRIMARY KEY value on database connection D, then this routine returns
** zero.






**
** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
** method, then this routine will return the [rowid] of the inserted
** row as long as the trigger or virtual table method is running.
** But once the trigger or virtual table method ends, the value returned 
** by this routine reverts to what it was before the trigger or virtual
** table method began.)^

Changes to src/sqliteInt.h.

1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
....
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
....
1443
1444
1445
1446
1447
1448
1449




1450
1451
1452
1453
1454
1455
1456
....
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
  int iSavepoint;           /* Depth of the SAVEPOINT stack */
  VTable *pNext;            /* Next in linked list (see above) */
};

/*
** Each SQL table is represented in memory by an instance of the
** following structure.
**
** Table.zName is the name of the table.  The case of the original
** CREATE TABLE statement is stored, but case is not significant for
** comparisons.
**
** Table.nCol is the number of columns in this table.  Table.aCol is a
** pointer to an array of Column structures, one for each column.
**
** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of
** the column that is that key.   Otherwise Table.iPKey is negative.  Note
** that the datatype of the PRIMARY KEY must be INTEGER for this field to
** be set.  An INTEGER PRIMARY KEY is used as the rowid for each row of
** the table.  If a table has no INTEGER PRIMARY KEY, then a random rowid
** is generated for each row of the table.  TF_HasPrimaryKey is set if
** the table has any PRIMARY KEY, INTEGER or otherwise.
**
** Table.tnum is the page number for the root BTree page of the table in the
** database file.  If Table.iDb is the index of the database table backend
** in sqlite.aDb[].  0 is for the main database and 1 is for the file that
** holds temporary tables and indices.  If TF_Ephemeral is set
** then the table is stored in a file that is automatically deleted
** when the VDBE cursor to the table is closed.  In this case Table.tnum 
** refers VDBE cursor number that holds the table open, not to the root
** page number.  Transient tables are used to hold the results of a
** sub-query that appears instead of a real table name in the FROM clause 
** of a SELECT statement.
*/
struct Table {
  char *zName;         /* Name of the table or view */
  int nCol;            /* Number of columns in this table */
  Column *aCol;        /* Information about each column */
  Index *pIndex;       /* List of SQL indexes on this table. */
  tRowcnt nRowEst;     /* Estimated rows in table - from sqlite_stat1 table */
................................................................................
  int nColumn;     /* Number of columns in the table used by this index */
  int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
  tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
  Table *pTable;   /* The SQL table being indexed */
  int tnum;        /* Page containing root of this index in database file */
  u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  u8 eIndexType;   /* SQLITE4_INDEX_USER, UNIQUE or PRIMARYKEY */
  u8 bUnordered;   /* Use this index for == or IN queries only */
  char *zColAff;   /* String defining the affinity of each column */
  Index *pNext;    /* The next index associated with the same table */
  Schema *pSchema; /* Schema containing this index */
  u8 *aSortOrder;  /* Array of size Index.nColumn. True==DESC, False==ASC */
  char **azColl;   /* Array of collation sequence names for index */
#ifdef SQLITE4_ENABLE_STAT3
  int nSample;             /* Number of elements in aSample[] */
................................................................................
/* Index.eIndexType must be set to one of the following. */
#define SQLITE4_INDEX_USER       0 /* Index created by CREATE INDEX statement */
#define SQLITE4_INDEX_UNIQUE     1 /* Index created by UNIQUE constraint */
#define SQLITE4_INDEX_PRIMARYKEY 2 /* Index is the tables PRIMARY KEY */
#define SQLITE4_INDEX_FTS5       3 /* Index is an FTS5 index */
#define SQLITE4_INDEX_TEMP       4 /* Index is an automatic index */





/*
** Each sample stored in the sqlite_stat3 table is represented in memory 
** using a structure of this type.  See documentation at the top of the
** analyze.c source file for additional information.
*/
struct IndexSample {
  union {
................................................................................
/*
** Bitfield flags for P5 value in OP_Insert and OP_Delete
*/
#define OPFLAG_NCHANGE       0x01    /* Set to update db->nChange */
#define OPFLAG_LASTROWID     0x02    /* Set to update db->lastRowid */
#define OPFLAG_ISUPDATE      0x04    /* This OP_Insert is an sql UPDATE */
#define OPFLAG_APPEND        0x08    /* This is likely to be an append */
#define OPFLAG_USESEEKRESULT 0x10    /* Try to avoid a seek on insert */
#define OPFLAG_CLEARCACHE    0x20    /* Clear pseudo-table cache in OP_Column */
#define OPFLAG_APPENDBIAS    0x40    /* Bias inserts for appending */

/*
 * Each trigger present in the database schema is stored as an instance of
 * struct Trigger. 
 *







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|







 







>
>
>
>







 







|







1181
1182
1183
1184
1185
1186
1187


























1188
1189
1190
1191
1192
1193
1194
....
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
....
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
....
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
  int iSavepoint;           /* Depth of the SAVEPOINT stack */
  VTable *pNext;            /* Next in linked list (see above) */
};

/*
** Each SQL table is represented in memory by an instance of the
** following structure.


























*/
struct Table {
  char *zName;         /* Name of the table or view */
  int nCol;            /* Number of columns in this table */
  Column *aCol;        /* Information about each column */
  Index *pIndex;       /* List of SQL indexes on this table. */
  tRowcnt nRowEst;     /* Estimated rows in table - from sqlite_stat1 table */
................................................................................
  int nColumn;     /* Number of columns in the table used by this index */
  int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
  tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
  Table *pTable;   /* The SQL table being indexed */
  int tnum;        /* Page containing root of this index in database file */
  u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  u8 eIndexType;   /* SQLITE4_INDEX_USER, UNIQUE or PRIMARYKEY */
  u8 fIndex;       /* One or more of the IDX_* flags below */
  char *zColAff;   /* String defining the affinity of each column */
  Index *pNext;    /* The next index associated with the same table */
  Schema *pSchema; /* Schema containing this index */
  u8 *aSortOrder;  /* Array of size Index.nColumn. True==DESC, False==ASC */
  char **azColl;   /* Array of collation sequence names for index */
#ifdef SQLITE4_ENABLE_STAT3
  int nSample;             /* Number of elements in aSample[] */
................................................................................
/* Index.eIndexType must be set to one of the following. */
#define SQLITE4_INDEX_USER       0 /* Index created by CREATE INDEX statement */
#define SQLITE4_INDEX_UNIQUE     1 /* Index created by UNIQUE constraint */
#define SQLITE4_INDEX_PRIMARYKEY 2 /* Index is the tables PRIMARY KEY */
#define SQLITE4_INDEX_FTS5       3 /* Index is an FTS5 index */
#define SQLITE4_INDEX_TEMP       4 /* Index is an automatic index */

/* Allowed values for Index.fIndex */
#define IDX_IntPK             0x01 /* An INTEGER PRIMARY KEY index */
#define IDX_Unordered         0x02 /* Implemented as a hashing index */

/*
** Each sample stored in the sqlite_stat3 table is represented in memory 
** using a structure of this type.  See documentation at the top of the
** analyze.c source file for additional information.
*/
struct IndexSample {
  union {
................................................................................
/*
** Bitfield flags for P5 value in OP_Insert and OP_Delete
*/
#define OPFLAG_NCHANGE       0x01    /* Set to update db->nChange */
#define OPFLAG_LASTROWID     0x02    /* Set to update db->lastRowid */
#define OPFLAG_ISUPDATE      0x04    /* This OP_Insert is an sql UPDATE */
#define OPFLAG_APPEND        0x08    /* This is likely to be an append */
#define OPFLAG_SEQCOUNT      0x10    /* Append sequence number to key */
#define OPFLAG_CLEARCACHE    0x20    /* Clear pseudo-table cache in OP_Column */
#define OPFLAG_APPENDBIAS    0x40    /* Bias inserts for appending */

/*
 * Each trigger present in the database schema is stored as an instance of
 * struct Trigger. 
 *

Changes to src/vdbe.c.

2181
2182
2183
2184
2185
2186
2187
2188
2189
2190




2191
2192
2193
2194
2195
2196
2197
....
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221



2222
2223
2224
2225
2226
2227
2228
....
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
....
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
....
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
**
** Or, if P4 is a non-zero integer, then it contains the value for N.
**
** This instruction encodes the N values into a database key and writes
** the result to register P3. No affinity transformations are applied to 
** the input values before they are encoded. 
**
** If P5 is non-zero, then a sequence number (unique within the cursor)
** is appended to the record. The sole purpose of this is to ensure that
** the key blob is unique within the cursors table.




*/
case OP_MakeIdxKey: {
  VdbeCursor *pC;
  KeyInfo *pKeyInfo;
  Mem *pData0;                    /* First in array of input registers */
  u8 *aRec;                       /* The constructed database key */
  int nRec;                       /* Size of aRec[] in bytes */
................................................................................
  aRec = 0;

  /* If pOp->p5 is non-zero, encode the sequence number blob to append to
  ** the end of the key. Variable nSeq is set to the number of bytes in
  ** the encoded key.
  */
  nSeq = 0;
  if( pOp->p5 ){
    iSeq = pC->seqCount++;
    do {
      nSeq++;
      aSeq[sizeof(aSeq)-nSeq] = (u8)(iSeq & 0x007F);
      iSeq = iSeq >> 7;
    }while( iSeq );
    aSeq[sizeof(aSeq)-nSeq] |= 0x80;



  }

  memAboutToChange(p, pOut);

  nField = pKeyInfo->nField;
  if( pOp->p4type==P4_INT32 && pOp->p4.i ){
    nField = pOp->p4.i;
................................................................................
  pOut->u.i = p->apCsr[pOp->p1]->seqCount++;
  break;
}


/* Opcode: NewRowid P1 P2 * * *
**
** Get a new integer record number (a.k.a "rowid") used as the key to a table.
** The record number is not previously used as a key in the database
** table that cursor P1 points to.  The new record number is written
** to register P2.
*/
case OP_NewRowid: {           /* out2-prerelease */
  i64 v;                   /* The new rowid */
  VdbeCursor *pC;          /* Cursor of table to get the new rowid */
  const KVByteArray *aKey; /* Key of an existing row */
  KVSize nKey;             /* Size of the existing row key */
  int n;                   /* Number of bytes decoded */
................................................................................
    if( rc==SQLITE4_OK ){
      n = sqlite4GetVarint64((u8 *)aKey, nKey, (u64 *)&v);
      if( n==0 ) rc = SQLITE4_CORRUPT_BKPT;
      if( v!=pC->iRoot ) rc = SQLITE4_CORRUPT_BKPT;
    }
    if( rc==SQLITE4_OK ){
      n = sqlite4VdbeDecodeIntKey(&aKey[n], nKey-n, &v);
      if( n==0 ) rc = SQLITE4_CORRUPT_BKPT;
    }
  }else{
    break;
  }
  pOut->flags = MEM_Int;
  pOut->u.i = v+1;
  break;
................................................................................
** be a MEM_Int.
**
** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is
** incremented (otherwise not).  If the OPFLAG_LASTROWID flag of P5 is set,
** then rowid is stored for subsequent return by the
** sqlite4_last_insert_rowid() function (otherwise it is unmodified).
**
** If the OPFLAG_USESEEKRESULT flag of P5 is set and if the result of
** the last seek operation (OP_NotExists) was a success, then this
** operation will not attempt to find the appropriate row before doing
** the insert but will instead overwrite the row that the cursor is
** currently pointing to.  Presumably, the prior OP_NotExists opcode
** has already positioned the cursor correctly.  This is an optimization
** that boosts performance by avoiding redundant seeks.
**
** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an
** UPDATE operation.  Otherwise (if the flag is clear) then this opcode
** is part of an INSERT operation.  The difference is only important to
** the update hook.
**
** Parameter P4 may point to a string containing the table-name, or 
** may be NULL. If it is not NULL, then the update-hook 







|
|
|
>
>
>
>







 







|







>
>
>







 







|
|
<
<







 







|







 







<
<
<
<
<
<
<
<







2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
....
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
....
3237
3238
3239
3240
3241
3242
3243
3244
3245


3246
3247
3248
3249
3250
3251
3252
....
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
....
3354
3355
3356
3357
3358
3359
3360








3361
3362
3363
3364
3365
3366
3367
**
** Or, if P4 is a non-zero integer, then it contains the value for N.
**
** This instruction encodes the N values into a database key and writes
** the result to register P3. No affinity transformations are applied to 
** the input values before they are encoded. 
**
** If the OPFLAG_SEQCOUNT bit of P5 is set, then a sequence number 
** (unique within the cursor) is appended to the record. The sole purpose
** of this is to ensure that the key blob is unique within the cursors table.
**
** If the OPFLAG_LASTROWID bit of P5 is set and the value of the first and
** only field of the key is an integer, then set the lastRowid field to the
** value of that integer.
*/
case OP_MakeIdxKey: {
  VdbeCursor *pC;
  KeyInfo *pKeyInfo;
  Mem *pData0;                    /* First in array of input registers */
  u8 *aRec;                       /* The constructed database key */
  int nRec;                       /* Size of aRec[] in bytes */
................................................................................
  aRec = 0;

  /* If pOp->p5 is non-zero, encode the sequence number blob to append to
  ** the end of the key. Variable nSeq is set to the number of bytes in
  ** the encoded key.
  */
  nSeq = 0;
  if( pOp->p5 & OPFLAG_SEQCOUNT ){
    iSeq = pC->seqCount++;
    do {
      nSeq++;
      aSeq[sizeof(aSeq)-nSeq] = (u8)(iSeq & 0x007F);
      iSeq = iSeq >> 7;
    }while( iSeq );
    aSeq[sizeof(aSeq)-nSeq] |= 0x80;
  }
  if( (pOp->p5 & OPFLAG_LASTROWID)!=0 && (pData0->flags & MEM_Int)!=0 ){
    lastRowid = pData0->u.i;
  }

  memAboutToChange(p, pOut);

  nField = pKeyInfo->nField;
  if( pOp->p4type==P4_INT32 && pOp->p4.i ){
    nField = pOp->p4.i;
................................................................................
  pOut->u.i = p->apCsr[pOp->p1]->seqCount++;
  break;
}


/* Opcode: NewRowid P1 P2 * * *
**
** Get a new integer primary key (a.k.a "rowid") for table P1.  The integer
** should not be currently in use as a primary key on that table.


*/
case OP_NewRowid: {           /* out2-prerelease */
  i64 v;                   /* The new rowid */
  VdbeCursor *pC;          /* Cursor of table to get the new rowid */
  const KVByteArray *aKey; /* Key of an existing row */
  KVSize nKey;             /* Size of the existing row key */
  int n;                   /* Number of bytes decoded */
................................................................................
    if( rc==SQLITE4_OK ){
      n = sqlite4GetVarint64((u8 *)aKey, nKey, (u64 *)&v);
      if( n==0 ) rc = SQLITE4_CORRUPT_BKPT;
      if( v!=pC->iRoot ) rc = SQLITE4_CORRUPT_BKPT;
    }
    if( rc==SQLITE4_OK ){
      n = sqlite4VdbeDecodeIntKey(&aKey[n], nKey-n, &v);
      if( n==0 || v==LARGEST_INT64 ) rc = SQLITE4_FULL;
    }
  }else{
    break;
  }
  pOut->flags = MEM_Int;
  pOut->u.i = v+1;
  break;
................................................................................
** be a MEM_Int.
**
** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is
** incremented (otherwise not).  If the OPFLAG_LASTROWID flag of P5 is set,
** then rowid is stored for subsequent return by the
** sqlite4_last_insert_rowid() function (otherwise it is unmodified).
**








** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an
** UPDATE operation.  Otherwise (if the flag is clear) then this opcode
** is part of an INSERT operation.  The difference is only important to
** the update hook.
**
** Parameter P4 may point to a string containing the table-name, or 
** may be NULL. If it is not NULL, then the update-hook 

Changes to src/where.c.

1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
....
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
  int iNext = nEqCol;             /* Index of next unmatched column in index */
  int nIdxCol;                    /* Number of columns in index, incl. PK */
  Index *pPk;
  Table *pTab;

  if( !pOrderBy ) return 0;
  if( wsFlags & WHERE_COLUMN_IN ) return 0;
  if( pIdx->bUnordered ) return 0;

  pTab = pIdx->pTable;
  pPk = sqlite4FindPrimaryKey(pTab, 0);
  nTerm = pOrderBy->nExpr;
  nIdxCol = pIdx->nColumn + (pIdx==pPk ? 0 : pPk->nColumn);

  assert( nTerm>0 );
................................................................................
    */
    if( nEq>=pProbe->nColumn && pProbe->onError!=OE_None ){
      testcase( wsFlags & WHERE_COLUMN_IN );
      testcase( wsFlags & WHERE_COLUMN_NULL );
      if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
        wsFlags |= WHERE_UNIQUE;
      }
    }else if( pProbe->bUnordered==0 ){
      int j = idxColumnNumber(pProbe, pPk, nEq);
      if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pProbe) ){
        WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pProbe);
        WhereTerm *pBtm = findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pProbe);
        whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &rangeDiv);
        if( pTop ){
          nBound = 1;







|







 







|







1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
....
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
  int iNext = nEqCol;             /* Index of next unmatched column in index */
  int nIdxCol;                    /* Number of columns in index, incl. PK */
  Index *pPk;
  Table *pTab;

  if( !pOrderBy ) return 0;
  if( wsFlags & WHERE_COLUMN_IN ) return 0;
  if( pIdx->fIndex & IDX_Unordered ) return 0;

  pTab = pIdx->pTable;
  pPk = sqlite4FindPrimaryKey(pTab, 0);
  nTerm = pOrderBy->nExpr;
  nIdxCol = pIdx->nColumn + (pIdx==pPk ? 0 : pPk->nColumn);

  assert( nTerm>0 );
................................................................................
    */
    if( nEq>=pProbe->nColumn && pProbe->onError!=OE_None ){
      testcase( wsFlags & WHERE_COLUMN_IN );
      testcase( wsFlags & WHERE_COLUMN_NULL );
      if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
        wsFlags |= WHERE_UNIQUE;
      }
    }else if( (pProbe->fIndex & IDX_Unordered)==0 ){
      int j = idxColumnNumber(pProbe, pPk, nEq);
      if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pProbe) ){
        WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pProbe);
        WhereTerm *pBtm = findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pProbe);
        whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &rangeDiv);
        if( pTop ){
          nBound = 1;

Changes to test/tkt-3a77c9714e.test.

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
    t2_id = (SELECT t3_id FROM
     ( SELECT t3_id FROM t3 WHERE t3_title=t1_title LIMIT 500 )
  )
} {ABCDEF ABCDEF}

do_execsql_test 2.1 {
  CREATE TABLE [Beginnings] (
    [Id] INTEGER PRIMARY KEY AUTOINCREMENT,[Title] TEXT, [EndingId] INTEGER
  );
  CREATE TABLE [Endings] (Id INT,Title TEXT,EndingId INT);
  INSERT INTO Beginnings (Id, Title, EndingId) VALUES (1, 'FACTOR', 18);
  INSERT INTO Beginnings (Id, Title, EndingId) VALUES (2, 'SWIMM', 18);
  INSERT INTO Endings (Id, Title, EndingId) VALUES (1, 'ING', 18);
}








|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
    t2_id = (SELECT t3_id FROM
     ( SELECT t3_id FROM t3 WHERE t3_title=t1_title LIMIT 500 )
  )
} {ABCDEF ABCDEF}

do_execsql_test 2.1 {
  CREATE TABLE [Beginnings] (
    [Id] INTEGER PRIMARY KEY /*AUTOINCREMENT*/,[Title] TEXT, [EndingId] INTEGER
  );
  CREATE TABLE [Endings] (Id INT,Title TEXT,EndingId INT);
  INSERT INTO Beginnings (Id, Title, EndingId) VALUES (1, 'FACTOR', 18);
  INSERT INTO Beginnings (Id, Title, EndingId) VALUES (2, 'SWIMM', 18);
  INSERT INTO Endings (Id, Title, EndingId) VALUES (1, 'ING', 18);
}

Changes to test/tkt3493.test.

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test tkt3493-1.1 {
  execsql {
    BEGIN;
    CREATE TABLE A (id INTEGER PRIMARY KEY AUTOINCREMENT, val TEXT);
    INSERT INTO A VALUES(1,'123');
    INSERT INTO A VALUES(2,'456');
    CREATE TABLE B (id INTEGER PRIMARY KEY AUTOINCREMENT, val TEXT);
    INSERT INTO B VALUES(1,1);
    INSERT INTO B VALUES(2,2);
    CREATE TABLE A_B (B_id INTEGER NOT NULL, A_id INTEGER);
    INSERT INTO A_B VALUES(1,1);
    INSERT INTO A_B VALUES(2,2);
    COMMIT;
  }







|


|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test tkt3493-1.1 {
  execsql {
    BEGIN;
    CREATE TABLE A (id INTEGER PRIMARY KEY /*AUTOINCREMENT*/, val TEXT);
    INSERT INTO A VALUES(1,'123');
    INSERT INTO A VALUES(2,'456');
    CREATE TABLE B (id INTEGER PRIMARY KEY /*AUTOINCREMENT*/, val TEXT);
    INSERT INTO B VALUES(1,1);
    INSERT INTO B VALUES(2,2);
    CREATE TABLE A_B (B_id INTEGER NOT NULL, A_id INTEGER);
    INSERT INTO A_B VALUES(1,1);
    INSERT INTO A_B VALUES(2,2);
    COMMIT;
  }