Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | STORED columns can now reference other STORED columns, in any order, as long as there are not loops. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | generated-columns |
Files: | files | file ages | folders |
SHA3-256: |
0d236698e64b2a4b46f91a25279c406e |
User & Date: | drh 2019-10-18 02:19:18.134 |
Context
2019-10-18
| ||
10:05 | Get indexes working on virtual columns. (check-in: 450c48766c user: drh tags: generated-columns) | |
02:19 | STORED columns can now reference other STORED columns, in any order, as long as there are not loops. (check-in: 0d236698e6 user: drh tags: generated-columns) | |
2019-10-17
| ||
18:35 | In the Table object, change the nVCol field to nNVCol - the number of non-virtual columns, as that is the quantity that we need most. (check-in: 4ad66af04a user: drh tags: generated-columns) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
3573 3574 3575 3576 3577 3578 3579 | sqlite3VdbeAddOp4(v, OP_Affinity, iReg, 1, 0, &zAff[(aff-'B')*2], P4_STATIC); } return iReg; } if( iTab<0 ){ if( pParse->iSelfTab<0 ){ | > | > > > > > | > > | > > | > > > > > | > > > > | > | > > > > > > > > > > | | 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 | sqlite3VdbeAddOp4(v, OP_Affinity, iReg, 1, 0, &zAff[(aff-'B')*2], P4_STATIC); } return iReg; } if( iTab<0 ){ if( pParse->iSelfTab<0 ){ /* Other columns in the same row for CHECK constraints or ** generated columns or for inserting into partial index. ** The row is unpacked into registers beginning at ** 0-(pParse->iSelfTab). The rowid (if any) is in a register ** immediately prior to the first column. */ Column *pCol; Table *pTab = pExpr->y.pTab; int iSrc; assert( pTab!=0 ); assert( pExpr->iColumn>=XN_ROWID ); assert( pExpr->iColumn<pExpr->y.pTab->nCol ); if( pExpr->iColumn<0 ){ return -1-pParse->iSelfTab; } pCol = pTab->aCol + pExpr->iColumn; iSrc = sqlite3ColumnOfTable(pTab, pExpr->iColumn) - pParse->iSelfTab; #ifndef SQLITE_OMIT_GENERATED_COLUMNS if( pCol->colFlags & COLFLAG_GENERATED ){ if( pCol->colFlags & COLFLAG_BUSY ){ sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pCol->zName); return 0; } pCol->colFlags |= COLFLAG_BUSY; if( pCol->colFlags & COLFLAG_VIRTUAL ){ target = sqlite3ExprCodeTarget(pParse, pCol->pDflt, target); }else{ target = iSrc; if( pCol->colFlags & COLFLAG_NOTAVAIL ){ sqlite3ExprCode(pParse, pCol->pDflt, iSrc); } } pCol->colFlags &= ~(COLFLAG_BUSY|COLFLAG_NOTAVAIL); return target; }else #endif /* SQLITE_OMIT_GENERATED_COLUMNS */ if( pCol->affinity==SQLITE_AFF_REAL ){ sqlite3VdbeAddOp2(v, OP_SCopy, iSrc, target); sqlite3VdbeAddOp1(v, OP_RealAffinity, target); return target; }else{ return iSrc; } }else{ /* Coding an expression that is part of an index where column names ** in the index refer to the table to which the index belongs */ iTab = pParse->iSelfTab - 1; } } |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
211 212 213 214 215 216 217 218 219 220 221 222 223 | */ 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 not stored */ iRegStore--; | > > > > > > > > > > > > > > | > | 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 241 242 243 244 245 246 247 248 | */ void sqlite3ComputeStoredColumns( Parse *pParse, /* Parsing context */ int iRegStore, /* Register holding the first column */ Table *pTab /* The table */ ){ int i; /* Because there can be multiple STORED columns that refer to one another, ** either directly or through VIRTUAL columns, this is a two pass ** algorithm. On the first pass, mark all STORED columns as NOT-AVAILABLE. */ for(i=0; i<pTab->nCol; i++){ if( pTab->aCol[i].colFlags & COLFLAG_STORED ){ pTab->aCol[i].colFlags |= COLFLAG_NOTAVAIL; } } /* On the second pass, compute the value of each NOT-AVAILABLE column. ** Companion code in the TK_COLUMN case of sqlite3ExprCodeTarget() will ** compute dependencies and mark remove the COLSPAN_NOTAVAIL mark, as ** they are needed. */ 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 not stored */ iRegStore--; }else if( (colFlags & COLFLAG_NOTAVAIL)!=0 ){ /* Stored columns are handled on the second pass */ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, iRegStore); colFlags &= ~COLFLAG_NOTAVAIL; } } pParse->iSelfTab = 0; } #endif /* SQLITE_OMIT_GENERATED_COLUMNS */ |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
1824 1825 1826 1827 1828 1829 1830 | struct Column { char *zName; /* Name of this column, \000, then the type */ Expr *pDflt; /* Default value or GENERATED ALWAYS AS value */ char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ char affinity; /* One of the SQLITE_AFF_... values */ u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */ | | | > | 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 | struct Column { char *zName; /* Name of this column, \000, then the type */ Expr *pDflt; /* Default value or GENERATED ALWAYS AS value */ char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ char affinity; /* One of the SQLITE_AFF_... values */ u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */ u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */ }; /* Allowed values for Column.colFlags: */ #define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */ #define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ #define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */ #define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */ #define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */ #define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */ #define COLFLAG_STORED 0x0040 /* GENERATED ALWAYS AS ... STORED */ #define COLFLAG_BUSY 0x0080 /* Blocks recursion on GENERATED columns */ #define COLFLAG_NOTAVAIL 0x0100 /* STORED column not yet calculated */ #define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */ #define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */ /* ** A "Collating Sequence" is defined by an instance of the following ** structure. Conceptually, a collating sequence consists of a name and ** a comparison routine that defines the order of that sequence. |
︙ | ︙ |