Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Some inserts and queries working for multi-column primary keys and WITHOUT ROWID. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | omit-rowid |
Files: | files | file ages | folders |
SHA1: |
b21d831b2aa55507dd9def2acb02cdbf |
User & Date: | drh 2013-10-23 13:30:58.697 |
Context
2013-10-23
| ||
16:03 | Get VACUUM and the xfer optimization working with WITHOUT ROWID. (check-in: 579815fff1 user: drh tags: omit-rowid) | |
13:30 | Some inserts and queries working for multi-column primary keys and WITHOUT ROWID. (check-in: b21d831b2a user: drh tags: omit-rowid) | |
01:57 | Some simple inserts and queries working on WITHOUT ROWID tables. (check-in: 3f8016dee2 user: drh tags: omit-rowid) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
4023 4024 4025 4026 4027 4028 4029 | ** the caller is responsible for calling sqlite3DbFree(db, ) on the returned ** pointer. If an error occurs (out of memory or missing collation ** sequence), NULL is returned and the state of pParse updated to reflect ** the error. */ KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){ int i; | | > | | | 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 | ** the caller is responsible for calling sqlite3DbFree(db, ) on the returned ** pointer. If an error occurs (out of memory or missing collation ** sequence), NULL is returned and the state of pParse updated to reflect ** the error. */ KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){ int i; int nCol = pIdx->nColumn; int nKey = pIdx->nKeyCol; KeyInfo *pKey; pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey); if( pKey ){ for(i=0; i<nCol; i++){ char *zColl = pIdx->azColl[i]; if( zColl==0 ) zColl = "BINARY"; pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl); pKey->aSortOrder[i] = pIdx->aSortOrder[i]; } } if( pParse->nErr ){ sqlite3DbFree(pParse->db, pKey); |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
1724 1725 1726 1727 1728 1729 1730 | ** if either column has NUMERIC or INTEGER affinity. If neither ** 'x' nor the SELECT... statement are columns, then numeric affinity ** is used. */ pExpr->iTable = pParse->nTab++; addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED); | | | 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 | ** if either column has NUMERIC or INTEGER affinity. If neither ** 'x' nor the SELECT... statement are columns, then numeric affinity ** is used. */ pExpr->iTable = pParse->nTab++; addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED); pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, 1, 1); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* Case 1: expr IN (SELECT ...) ** ** Generate code to write the results of the select into the temporary ** table allocated and opened above. */ |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
65 66 67 68 69 70 71 | ** The column affinity string will eventually be deleted by ** sqliteDeleteIndex() when the Index structure itself is cleaned ** up. */ int n; Table *pTab = pIdx->pTable; sqlite3 *db = sqlite3VdbeDb(v); | | | | > < | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | ** The column affinity string will eventually be deleted by ** sqliteDeleteIndex() when the Index structure itself is cleaned ** up. */ int n; Table *pTab = pIdx->pTable; sqlite3 *db = sqlite3VdbeDb(v); pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1); if( !pIdx->zColAff ){ db->mallocFailed = 1; return 0; } for(n=0; n<pIdx->nColumn; n++){ i16 x = pIdx->aiColumn[n]; pIdx->zColAff[n] = x<0 ? SQLITE_AFF_INTEGER : pTab->aCol[x].affinity; } pIdx->zColAff[n] = 0; } return pIdx->zColAff; } /* |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
799 800 801 802 803 804 805 | */ if( pOrderBy==0 && p->iLimit ){ sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); } } /* | | > | | | > | 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 | */ if( pOrderBy==0 && p->iLimit ){ sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); } } /* ** Allocate a KeyInfo object sufficient for an index of N key columns and ** X extra columns. ** ** Actually, always allocate one extra column for the rowid at the end ** of the index. So the KeyInfo returned will have space sufficient for ** N+1 columns. */ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ KeyInfo *p = sqlite3DbMallocZero(db, sizeof(KeyInfo) + (N+X)*(sizeof(CollSeq*)+1)); if( p ){ p->aSortOrder = (u8*)&p->aColl[N+X]; p->nField = (u16)N; p->nXField = (u16)X; p->enc = ENC(db); p->db = db; } return p; } /* |
︙ | ︙ | |||
840 841 842 843 844 845 846 | int nExpr; KeyInfo *pInfo; struct ExprList_item *pItem; sqlite3 *db = pParse->db; int i; nExpr = pList->nExpr; | | | 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 | int nExpr; KeyInfo *pInfo; struct ExprList_item *pItem; sqlite3 *db = pParse->db; int i; nExpr = pList->nExpr; pInfo = sqlite3KeyInfoAlloc(db, nExpr, 1); if( pInfo ){ for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){ CollSeq *pColl; pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); if( !pColl ) pColl = db->pDfltColl; pInfo->aColl[i] = pColl; pInfo->aSortOrder[i] = pItem->sortOrder; |
︙ | ︙ | |||
1984 1985 1986 1987 1988 1989 1990 | KeyInfo *pKeyInfo; /* Collating sequence for the result set */ Select *pLoop; /* For looping through SELECT statements */ CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ int nCol; /* Number of columns in result set */ assert( p->pRightmost==p ); nCol = p->pEList->nExpr; | | | 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 | KeyInfo *pKeyInfo; /* Collating sequence for the result set */ Select *pLoop; /* For looping through SELECT statements */ CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ int nCol; /* Number of columns in result set */ assert( p->pRightmost==p ); nCol = p->pEList->nExpr; pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1); if( !pKeyInfo ){ rc = SQLITE_NOMEM; goto multi_select_end; } for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){ *apColl = multiSelectCollSeq(pParse, p, i); if( 0==*apColl ){ |
︙ | ︙ | |||
2363 2364 2365 2366 2367 2368 2369 | aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy); if( aPermute ){ struct ExprList_item *pItem; for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){ assert( pItem->iOrderByCol>0 && pItem->iOrderByCol<=p->pEList->nExpr ); aPermute[i] = pItem->iOrderByCol - 1; } | | | 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 | aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy); if( aPermute ){ struct ExprList_item *pItem; for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){ assert( pItem->iOrderByCol>0 && pItem->iOrderByCol<=p->pEList->nExpr ); aPermute[i] = pItem->iOrderByCol - 1; } pKeyMerge = sqlite3KeyInfoAlloc(db, nOrderBy, 1); if( pKeyMerge ){ for(i=0; i<nOrderBy; i++){ CollSeq *pColl; Expr *pTerm = pOrderBy->a[i].pExpr; if( pTerm->flags & EP_Collate ){ pColl = sqlite3ExprCollSeq(pParse, pTerm); }else{ |
︙ | ︙ | |||
2401 2402 2403 2404 2405 2406 2407 | regPrev = 0; }else{ int nExpr = p->pEList->nExpr; assert( nOrderBy>=nExpr || db->mallocFailed ); regPrev = pParse->nMem+1; pParse->nMem += nExpr+1; sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev); | | | 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 | regPrev = 0; }else{ int nExpr = p->pEList->nExpr; assert( nOrderBy>=nExpr || db->mallocFailed ); regPrev = pParse->nMem+1; pParse->nMem += nExpr+1; sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev); pKeyDup = sqlite3KeyInfoAlloc(db, nExpr, 1); if( pKeyDup ){ for(i=0; i<nExpr; i++){ pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i); pKeyDup->aSortOrder[i] = 0; } } } |
︙ | ︙ | |||
4650 4651 4652 4653 4654 4655 4656 | } if( pBest ){ iRoot = pBest->tnum; pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest); } /* Open a read-only cursor, execute the OP_Count, close the cursor. */ | | > | 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 | } if( pBest ){ iRoot = pBest->tnum; pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest); } /* Open a read-only cursor, execute the OP_Count, close the cursor. */ sqlite3VdbeAddOp4(v, OP_OpenRead, iCsr, iRoot, iDb, SQLITE_INT_TO_PTR(1), P4_INT32); if( pKeyInfo ){ sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO_HANDOFF); } sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem); sqlite3VdbeAddOp1(v, OP_Close, iCsr); explainSimpleCount(pParse, pTab, pBest); }else |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
1514 1515 1516 1517 1518 1519 1520 | ** Note that aSortOrder[] and aColl[] have nField+1 slots. There ** are nField slots for the columns of an index then one extra slot ** for the rowid at the end. */ struct KeyInfo { sqlite3 *db; /* The database connection */ u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ | | > | 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 | ** Note that aSortOrder[] and aColl[] have nField+1 slots. There ** are nField slots for the columns of an index then one extra slot ** for the rowid at the end. */ struct KeyInfo { sqlite3 *db; /* The database connection */ u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ u16 nField; /* Number of key columns in the index */ u16 nXField; /* Number of columns beyond the key columns */ u8 *aSortOrder; /* Sort order for each column. */ CollSeq *aColl[1]; /* Collating sequence for each term of the key */ }; /* ** An instance of the following structure holds information about a ** single index record that has already been parsed out into individual |
︙ | ︙ | |||
3135 3136 3137 3138 3139 3140 3141 | void sqlite3DefaultRowEst(Index*); void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); void sqlite3MinimumFileFormat(Parse*, int, int); void sqlite3SchemaClear(void *); Schema *sqlite3SchemaGet(sqlite3 *, Btree *); int sqlite3SchemaToIndex(sqlite3 *db, Schema *); | | | 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 | void sqlite3DefaultRowEst(Index*); void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); void sqlite3MinimumFileFormat(Parse*, int, int); void sqlite3SchemaClear(void *); Schema *sqlite3SchemaGet(sqlite3 *, Btree *); int sqlite3SchemaToIndex(sqlite3 *db, Schema *); KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int); KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *); int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), FuncDestructor *pDestructor ); int sqlite3ApiExit(sqlite3 *db, int); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
3214 3215 3216 3217 3218 3219 3220 | rc = SQLITE_CORRUPT_BKPT; goto abort_due_to_error; } } if( pOp->p4type==P4_KEYINFO ){ pKeyInfo = pOp->p4.pKeyInfo; pKeyInfo->enc = ENC(p->db); | | | 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 | rc = SQLITE_CORRUPT_BKPT; goto abort_due_to_error; } } if( pOp->p4type==P4_KEYINFO ){ pKeyInfo = pOp->p4.pKeyInfo; pKeyInfo->enc = ENC(p->db); nField = pKeyInfo->nField+pKeyInfo->nXField; }else if( pOp->p4type==P4_INT32 ){ nField = pOp->p4.i; } assert( pOp->p1>=0 ); pCur = allocateCursor(p, pOp->p1, nField, iDb, 1); if( pCur==0 ) goto no_mem; pCur->nullRow = 1; |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
748 749 750 751 752 753 754 | }else if( zP4==0 ){ pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; }else if( n==P4_KEYINFO ){ KeyInfo *pOrig, *pNew; pOrig = (KeyInfo*)zP4; | > | > | | | 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 | }else if( zP4==0 ){ pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; }else if( n==P4_KEYINFO ){ KeyInfo *pOrig, *pNew; pOrig = (KeyInfo*)zP4; pNew = sqlite3KeyInfoAlloc(db, pOrig->nField, pOrig->nXField); pOp->p4.pKeyInfo = pNew; if( pNew ){ int n = pOrig->nField+pOrig->nXField; memcpy(pNew->aColl, pOrig->aColl, n*sizeof(pNew->aColl[0])); memcpy(pNew->aSortOrder, pOrig->aSortOrder, n); pOp->p4type = P4_KEYINFO; }else{ p->db->mallocFailed = 1; pOp->p4type = P4_NOTUSED; } }else if( n==P4_KEYINFO_HANDOFF ){ pOp->p4.p = (void*)zP4; |
︙ | ︙ |
Changes to test/alter.test.
︙ | ︙ | |||
859 860 861 862 863 864 865 | catchsql "ALTER TABLE $tbl ADD COLUMN xyz" } [list 1 "table $tbl may not be altered"] } #------------------------------------------------------------------------ # Verify that ALTER TABLE works on tables with the WITHOUT rowid option. # | < < | 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 | catchsql "ALTER TABLE $tbl ADD COLUMN xyz" } [list 1 "table $tbl may not be altered"] } #------------------------------------------------------------------------ # Verify that ALTER TABLE works on tables with the WITHOUT rowid option. # do_execsql_test alter-16.1 { CREATE TABLE t16a(a TEXT, b REAL, c INT, PRIMARY KEY(a,b)) WITHOUT rowid; INSERT INTO t16a VALUES('abc',1.25,99); ALTER TABLE t16a ADD COLUMN d TEXT DEFAULT 'xyzzy'; INSERT INTO t16a VALUES('cba',5.5,98,'fizzle'); SELECT * FROM t16a ORDER BY a; } {abc 1.25 99 xyzzy cba 5.5 98 fizzle} do_execsql_test alter-16.2 { ALTER TABLE t16a RENAME TO t16a_rn; SELECT * FROM t16a_rn ORDER BY a; } {abc 1.25 99 xyzzy cba 5.5 98 fizzle} finish_test |