/ Check-in [fe7517bf]
Login

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

Overview
Comment:Some (but not all) INSERT and UPDATE statements now work for STORED columns.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | generated-columns
Files: files | file ages | folders
SHA3-256: fe7517bf4d360597576ab9aba29627d7926d23f2bbbfb3e7bf4d32761617574c
User & Date: drh 2019-10-17 17:54:05
Context
2019-10-17
18:07
Bug fix with INSERT using an explicit column list on a table with a non-final STORED column. check-in: 61b4459a user: drh tags: generated-columns
17:54
Some (but not all) INSERT and UPDATE statements now work for STORED columns. check-in: fe7517bf user: drh tags: generated-columns
16:16
Fix the xfer optimization for generated columns, so that VACUUM works again. check-in: 8f67b89b user: drh tags: generated-columns
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

1560
1561
1562
1563
1564
1565
1566
1567
1568



1569
1570
1571
1572
1573
1574
1575
....
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
      /* no-op */
    }else if( pType->n==6 && sqlite3StrNICmp("stored",pType->z,6)==0 ){
      eType = COLFLAG_STORED;
    }else{
      goto generated_error;
    }
  }
  pTab->nVCol++;
  pCol->colFlags |= eType;



  pCol->pDflt = sqlite3ExprDup(pParse->db, pExpr, 0);
  goto generated_done;

generated_error:
  sqlite3ErrorMsg(pParse, "incorrect GENERATED ALWAYS AS on column \"%s\"",
                  pCol->zName);
generated_done:
................................................................................
  /* Resolve names in all CHECK constraint expressions.
  */
  if( p->pCheck ){
    sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
  }
#endif /* !defined(SQLITE_OMIT_CHECK) */
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
  if( p->nVCol ){
    int ii;
    for(ii=0; ii<p->nCol; ii++){
      if( (p->aCol[ii].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL))!=0 ){
        sqlite3ResolveSelfReference(pParse, p, NC_GenCol, 
                                    p->aCol[ii].pDflt, 0);
      }
    }







|

>
>
>







 







|







1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
....
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
      /* no-op */
    }else if( pType->n==6 && sqlite3StrNICmp("stored",pType->z,6)==0 ){
      eType = COLFLAG_STORED;
    }else{
      goto generated_error;
    }
  }
  if( eType==COLFLAG_VIRTUAL ) pTab->nVCol++;
  pCol->colFlags |= eType;
  assert( TF_HasVirtual==COLFLAG_VIRTUAL );
  assert( TF_HasStored==COLFLAG_STORED );
  pTab->tabFlags |= eType;
  pCol->pDflt = sqlite3ExprDup(pParse->db, pExpr, 0);
  goto generated_done;

generated_error:
  sqlite3ErrorMsg(pParse, "incorrect GENERATED ALWAYS AS on column \"%s\"",
                  pCol->zName);
generated_done:
................................................................................
  /* Resolve names in all CHECK constraint expressions.
  */
  if( p->pCheck ){
    sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
  }
#endif /* !defined(SQLITE_OMIT_CHECK) */
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
  if( p->tabFlags & (TF_HasVirtual|TF_HasStored) ){
    int ii;
    for(ii=0; ii<p->nCol; ii++){
      if( (p->aCol[ii].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL))!=0 ){
        sqlite3ResolveSelfReference(pParse, p, NC_GenCol, 
                                    p->aCol[ii].pDflt, 0);
      }
    }

Changes to src/insert.c.

197
198
199
200
201
202
203






























204
205
206
207
208
209
210
....
1023
1024
1025
1026
1027
1028
1029
1030
1031


1032
1033
1034
1035
1036
1037
1038
1039
....
1056
1057
1058
1059
1060
1061
1062








1063
1064
1065
1066
1067
1068
1069
      assert( pOp->p4type==P4_VTAB );
      return 1;
    }
#endif
  }
  return 0;
}































#ifndef SQLITE_OMIT_AUTOINCREMENT
/*
** Locate or create an AutoincInfo structure associated with table pTab
** which is in database iDb.  Return the register number for the register
** that holds the maximum rowid.  Return zero if pTab is not an AUTOINCREMENT
** table.  (Also return zero when doing a VACUUM since we do not want to
................................................................................
      }
      if( ((colFlags = pTab->aCol[i].colFlags) & COLFLAG_NOINSERT)!=0 ){
        nHidden++;
        if( (colFlags & COLFLAG_VIRTUAL)!=0 ){
          /* Virtual columns are no stored */
          iRegStore--;
          continue;
        }else if( (colFlags & COLFLAG_STORED)!=0 || pColumn==0 ){
          /* Stored columns get the default value.  Also hidden columns


          ** that are not explicitly named in the INSERT */
          sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
          continue;
        }
      }
      if( pColumn ){
        for(j=0; j<pColumn->nId && pColumn->a[j].idx!=i; j++){}
        if( j>=pColumn->nId ){
................................................................................
        if( regFromSelect!=regData ){
          sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+k, iRegStore);
        }
      }else{
        sqlite3ExprCode(pParse, pList->a[k].pExpr, iRegStore);
      }
    }









    /* Generate code to check constraints and generate index keys and
    ** do the insertion.
    */
#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( IsVirtual(pTab) ){
      const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);







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







 







|
|
>
>
|







 







>
>
>
>
>
>
>
>







197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
....
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
....
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
      assert( pOp->p4type==P4_VTAB );
      return 1;
    }
#endif
  }
  return 0;
}

#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/*
** All regular columns for table pTab have been puts into registers
** starting with iRegStore.  The registers that correspond to STORED
** columns have not been initialized.  This routine goes back and computes
** the values for STORED columns based on the previously computed normal
** columns.
*/
void sqlite3ComputeStoredColumns(
  Parse *pParse,    /* Parsing context */
  int iRegStore,    /* Register holding the first column */
  Table *pTab       /* The table */
){
  int i;
  pParse->iSelfTab = -iRegStore;
  for(i=0; i<pTab->nCol; i++, iRegStore++){
    u32 colFlags = pTab->aCol[i].colFlags;
    if( (colFlags & COLFLAG_VIRTUAL)!=0 ){
      /* Virtual columns are no stored */
      iRegStore--;
    }else if( (colFlags & COLFLAG_STORED)!=0 ){
      /* Stored columns are handled on the second pass */
      sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, iRegStore);
    }
  }
  pParse->iSelfTab = 0;
}
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */


#ifndef SQLITE_OMIT_AUTOINCREMENT
/*
** Locate or create an AutoincInfo structure associated with table pTab
** which is in database iDb.  Return the register number for the register
** that holds the maximum rowid.  Return zero if pTab is not an AUTOINCREMENT
** table.  (Also return zero when doing a VACUUM since we do not want to
................................................................................
      }
      if( ((colFlags = pTab->aCol[i].colFlags) & COLFLAG_NOINSERT)!=0 ){
        nHidden++;
        if( (colFlags & COLFLAG_VIRTUAL)!=0 ){
          /* Virtual columns are no stored */
          iRegStore--;
          continue;
        }else if( (colFlags & COLFLAG_STORED)!=0 ){
          /* Stored columns are handled on the second pass */
          continue;
        }else if( pColumn==0 ){
          /* Hidden columns that are not explicitly named in the INSERT */
          sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
          continue;
        }
      }
      if( pColumn ){
        for(j=0; j<pColumn->nId && pColumn->a[j].idx!=i; j++){}
        if( j>=pColumn->nId ){
................................................................................
        if( regFromSelect!=regData ){
          sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+k, iRegStore);
        }
      }else{
        sqlite3ExprCode(pParse, pList->a[k].pExpr, iRegStore);
      }
    }

#ifndef SQLITE_OMIT_GENERATED_COLUMNS
    /* Compute the new value for STORED columns after all other
    ** columns have already been computed */
    if( pTab->tabFlags & TF_HasStored ){
      sqlite3ComputeStoredColumns(pParse, regRowid+1, pTab);
    }
#endif

    /* Generate code to check constraints and generate index keys and
    ** do the insertion.
    */
#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( IsVirtual(pTab) ){
      const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);

Changes to src/pragma.c.

1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
        if( pCol->colFlags & COLFLAG_NOINSERT ){
          if( pPragma->iArg==0 ){
            nHidden++;
            continue;
          }
          if( pCol->colFlags & COLFLAG_VIRTUAL ){
            isHidden = 2;  /* GENERATED ALWAYS AS ... VIRTUAL */
          }else if( pCol->colFlags & COLFLAG_VIRTUAL ){
            isHidden = 3;  /* GENERATED ALWAYS AS ... STORED */
          }else{
            isHidden = 1;  /* HIDDEN */
          }
        }
        if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
          k = 0;
        }else if( pPk==0 ){
          k = 1;







|

|







1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
        if( pCol->colFlags & COLFLAG_NOINSERT ){
          if( pPragma->iArg==0 ){
            nHidden++;
            continue;
          }
          if( pCol->colFlags & COLFLAG_VIRTUAL ){
            isHidden = 2;  /* GENERATED ALWAYS AS ... VIRTUAL */
          }else if( pCol->colFlags & COLFLAG_STORED ){
            isHidden = 3;  /* GENERATED ALWAYS AS ... STORED */
          }else{ assert( pCol->colFlags & COLFLAG_HIDDEN );
            isHidden = 1;  /* HIDDEN */
          }
        }
        if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
          k = 0;
        }else if( pPk==0 ){
          k = 1;

Changes to src/sqliteInt.h.

2005
2006
2007
2008
2009
2010
2011
2012





2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023


2024
2025
2026
2027
2028
2029
2030
2031
2032
....
4016
4017
4018
4019
4020
4021
4022



4023
4024
4025
4026
4027
4028
4029
/*
** Allowed values for Table.tabFlags.
**
** TF_OOOHidden applies to tables or view that have hidden columns that are
** followed by non-hidden columns.  Example:  "CREATE VIRTUAL TABLE x USING
** vtab1(a HIDDEN, b);".  Since "b" is a non-hidden column but "a" is hidden,
** the TF_OOOHidden attribute would apply in this case.  Such tables require
** special handling during INSERT processing.





*/
#define TF_Readonly        0x0001    /* Read-only system table */
#define TF_Ephemeral       0x0002    /* An ephemeral table */
#define TF_HasPrimaryKey   0x0004    /* Table has a primary key */
#define TF_Autoincrement   0x0008    /* Integer primary key is autoincrement */
#define TF_HasStat1        0x0010    /* nRowLogEst set from sqlite_stat1 */
#define TF_WithoutRowid    0x0020    /* No rowid.  PRIMARY KEY is the key */
#define TF_NoVisibleRowid  0x0040    /* No user-visible "rowid" column */
#define TF_OOOHidden       0x0080    /* Out-of-Order hidden columns */
#define TF_StatsUsed       0x0100    /* Query planner decisions affected by
                                     ** Index.aiRowLogEst[] values */


#define TF_HasNotNull      0x0200    /* Contains NOT NULL constraints */
#define TF_Shadow          0x0400    /* True for a shadow table */

/*
** Test to see whether or not a table is a virtual table.  This is
** done as a macro so that it will be optimized out when virtual
** table support is omitted from the build.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
................................................................................
  void sqlite3AutoincrementBegin(Parse *pParse);
  void sqlite3AutoincrementEnd(Parse *pParse);
#else
# define sqlite3AutoincrementBegin(X)
# define sqlite3AutoincrementEnd(X)
#endif
void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);



void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
int sqlite3IdListIndex(IdList*,const char*);
SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
                                      Token*, Select*, Expr*, IdList*);







|
>
>
>
>
>






|
|
|


>
>
|
|







 







>
>
>







2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
....
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
/*
** Allowed values for Table.tabFlags.
**
** TF_OOOHidden applies to tables or view that have hidden columns that are
** followed by non-hidden columns.  Example:  "CREATE VIRTUAL TABLE x USING
** vtab1(a HIDDEN, b);".  Since "b" is a non-hidden column but "a" is hidden,
** the TF_OOOHidden attribute would apply in this case.  Such tables require
** special handling during INSERT processing. The "OOO" means "Out Of Order".
**
** Constraints:
**
**         TF_HasVirtual == COLFLAG_Virtual
**         TF_HasStored  == COLFLAG_Stored
*/
#define TF_Readonly        0x0001    /* Read-only system table */
#define TF_Ephemeral       0x0002    /* An ephemeral table */
#define TF_HasPrimaryKey   0x0004    /* Table has a primary key */
#define TF_Autoincrement   0x0008    /* Integer primary key is autoincrement */
#define TF_HasStat1        0x0010    /* nRowLogEst set from sqlite_stat1 */
#define TF_HasVirtual      0x0020    /* Has one or more VIRTUAL columns */
#define TF_HasStored       0x0040    /* Has one or more STORED columns */
#define TF_WithoutRowid    0x0080    /* No rowid.  PRIMARY KEY is the key */
#define TF_StatsUsed       0x0100    /* Query planner decisions affected by
                                     ** Index.aiRowLogEst[] values */
#define TF_NoVisibleRowid  0x0200    /* No user-visible "rowid" column */
#define TF_OOOHidden       0x0400    /* Out-of-Order hidden columns */
#define TF_HasNotNull      0x0800    /* Contains NOT NULL constraints */
#define TF_Shadow          0x1000    /* True for a shadow table */

/*
** Test to see whether or not a table is a virtual table.  This is
** done as a macro so that it will be optimized out when virtual
** table support is omitted from the build.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
................................................................................
  void sqlite3AutoincrementBegin(Parse *pParse);
  void sqlite3AutoincrementEnd(Parse *pParse);
#else
# define sqlite3AutoincrementBegin(X)
# define sqlite3AutoincrementEnd(X)
#endif
void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
  void sqlite3ComputeStoredColumns(Parse*, int, Table*);
#endif
void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
int sqlite3IdListIndex(IdList*,const char*);
SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
                                      Token*, Select*, Expr*, IdList*);

Changes to src/update.c.

667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
...
687
688
689
690
691
692
693





694
695
696
697
698
699
700
...
720
721
722
723
724
725
726

727
728
729
730
731
732





733
734
735
736
737
738
739
  */
  newmask = sqlite3TriggerColmask(
      pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
  );
  for(i=0, k=regNew; i<pTab->nCol; i++, k++){
    if( i==pTab->iPKey ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, k);
    }else if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)!=0 ){
      k--;
    }else{
      j = aXRef[i];
      if( j>=0 ){
        sqlite3ExprCode(pParse, pChanges->a[j].pExpr, k);
      }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
        /* This branch loads the value of a column that will not be changed 
        ** into a register. This is done if there are no BEFORE triggers, or
................................................................................
        testcase( i==32 );
        sqlite3ExprCodeGetColumnOfTable(pParse, pTab, iDataCur, i, k);
      }else{
        sqlite3VdbeAddOp2(v, OP_Null, 0, k);
      }
    }
  }






  /* Fire any BEFORE UPDATE triggers. This happens before constraints are
  ** verified. One could argue that this is wrong.
  */
  if( tmask&TRIGGER_BEFORE ){
    sqlite3TableAffinity(v, pTab, regNew);
    sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, 
................................................................................
    ** all columns not modified by the update statement into their registers
    ** in case this has happened. Only unmodified columns are reloaded.
    ** The values computed for modified columns use the values before the
    ** BEFORE trigger runs.  See test case trigger1-18.0 (added 2018-04-26)
    ** for an example.
    */
    for(i=0, k=regNew; i<pTab->nCol; i++, k++){

      if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ){
        k--;
      }else if( aXRef[i]<0 && i!=pTab->iPKey ){
        sqlite3ExprCodeGetColumnOfTable(pParse, pTab, iDataCur, i, k);
      }
    }





  }

  if( !isView ){
    /* Do constraint checks. */
    assert( regOldRowid>0 );
    sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
        regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace,







|
|







 







>
>
>
>
>







 







>
|
<




>
>
>
>
>







667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
...
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
...
725
726
727
728
729
730
731
732
733

734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
  */
  newmask = sqlite3TriggerColmask(
      pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
  );
  for(i=0, k=regNew; i<pTab->nCol; i++, k++){
    if( i==pTab->iPKey ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, k);
    }else if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)!=0 ){
      if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--;
    }else{
      j = aXRef[i];
      if( j>=0 ){
        sqlite3ExprCode(pParse, pChanges->a[j].pExpr, k);
      }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
        /* This branch loads the value of a column that will not be changed 
        ** into a register. This is done if there are no BEFORE triggers, or
................................................................................
        testcase( i==32 );
        sqlite3ExprCodeGetColumnOfTable(pParse, pTab, iDataCur, i, k);
      }else{
        sqlite3VdbeAddOp2(v, OP_Null, 0, k);
      }
    }
  }
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
  if( pTab->tabFlags & TF_HasStored ){
    sqlite3ComputeStoredColumns(pParse, regNew, pTab);
  }
#endif

  /* Fire any BEFORE UPDATE triggers. This happens before constraints are
  ** verified. One could argue that this is wrong.
  */
  if( tmask&TRIGGER_BEFORE ){
    sqlite3TableAffinity(v, pTab, regNew);
    sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, 
................................................................................
    ** all columns not modified by the update statement into their registers
    ** in case this has happened. Only unmodified columns are reloaded.
    ** The values computed for modified columns use the values before the
    ** BEFORE trigger runs.  See test case trigger1-18.0 (added 2018-04-26)
    ** for an example.
    */
    for(i=0, k=regNew; i<pTab->nCol; i++, k++){
      if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
        if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--;

      }else if( aXRef[i]<0 && i!=pTab->iPKey ){
        sqlite3ExprCodeGetColumnOfTable(pParse, pTab, iDataCur, i, k);
      }
    }
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
    if( pTab->tabFlags & TF_HasStored ){
      sqlite3ComputeStoredColumns(pParse, regNew, pTab);
    }
#endif 
  }

  if( !isView ){
    /* Do constraint checks. */
    assert( regOldRowid>0 );
    sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
        regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace,

Changes to src/vtab.c.

620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
    if( sCtx.bDeclared==0 ){
      const char *zFormat = "vtable constructor did not declare schema: %s";
      *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
      sqlite3VtabUnlock(pVTable);
      rc = SQLITE_ERROR;
    }else{
      int iCol;
      u8 oooHidden = 0;
      /* If everything went according to plan, link the new VTable structure
      ** into the linked list headed by pTab->pVTable. Then loop through the 
      ** columns of the table to see if any of them contain the token "hidden".
      ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
      ** the type string.  */
      pVTable->pNext = pTab->pVTable;
      pTab->pVTable = pVTable;







|







620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
    if( sCtx.bDeclared==0 ){
      const char *zFormat = "vtable constructor did not declare schema: %s";
      *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
      sqlite3VtabUnlock(pVTable);
      rc = SQLITE_ERROR;
    }else{
      int iCol;
      u16 oooHidden = 0;
      /* If everything went according to plan, link the new VTable structure
      ** into the linked list headed by pTab->pVTable. Then loop through the 
      ** columns of the table to see if any of them contain the token "hidden".
      ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
      ** the type string.  */
      pVTable->pNext = pTab->pVTable;
      pTab->pVTable = pVTable;