diff options
author | drh <> | 2024-05-18 20:00:08 +0000 |
---|---|---|
committer | drh <> | 2024-05-18 20:00:08 +0000 |
commit | 04624990514ae7c593ad224dd87cd9037cec752f (patch) | |
tree | 88e3ed5bd9703df77b9193cf3594eb557d049a70 /src | |
parent | 79dac84b315ced19266d55f769341782f429e6b4 (diff) | |
download | sqlite-04624990514ae7c593ad224dd87cd9037cec752f.tar.gz sqlite-04624990514ae7c593ad224dd87cd9037cec752f.zip |
Fix the definition of sqlite3_vtab_distinct() such that return codes 2 and
3 mean that all rows must be distinct over "colUsed" which is a superset of
"aOrderBy". Also, disallow return codes 2 and 3 if the rowid of the virtual
table is accessed.
FossilOrigin-Name: 922731ce98c0ce7837784ff7966049e59fa73da2aa04abf3506503b6fc4aa048
Diffstat (limited to 'src')
-rw-r--r-- | src/resolve.c | 8 | ||||
-rw-r--r-- | src/sqlite.h.in | 16 | ||||
-rw-r--r-- | src/sqliteInt.h | 1 | ||||
-rw-r--r-- | src/treeview.c | 6 | ||||
-rw-r--r-- | src/where.c | 2 |
5 files changed, 21 insertions, 12 deletions
diff --git a/src/resolve.c b/src/resolve.c index 546731afe..bf8326aa6 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -828,8 +828,12 @@ static int lookupName( ** If a generated column is referenced, set bits for every column ** of the table. */ - if( pExpr->iColumn>=0 && cnt==1 && pMatch!=0 ){ - pMatch->colUsed |= sqlite3ExprColUsed(pExpr); + if( pMatch ){ + if( pExpr->iColumn>=0 ){ + pMatch->colUsed |= sqlite3ExprColUsed(pExpr); + }else{ + pMatch->fg.rowidUsed = 1; + } } pExpr->op = eNewExprOp; diff --git a/src/sqlite.h.in b/src/sqlite.h.in index d553abb7b..459af929b 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -9942,20 +9942,22 @@ const char *sqlite3_vtab_collation(sqlite3_index_info*,int); ** <li value="2"><p> ** ^(If the sqlite3_vtab_distinct() interface returns 2, that means ** that the query planner does not need the rows returned in any particular -** order, as long as rows with the same values in all "aOrderBy" columns +** order, as long as rows with the same values in all "colUsed" columns ** are adjacent.)^ ^(Furthermore, only a single row for each particular -** combination of values in the columns identified by the "aOrderBy" field +** combination of values in the columns identified by the "colUsed" field ** needs to be returned.)^ ^It is always ok for two or more rows with the same -** values in all "aOrderBy" columns to be returned, as long as all such rows +** values in all "colUsed" columns to be returned, as long as all such rows ** are adjacent. ^The virtual table may, if it chooses, omit extra rows -** that have the same value for all columns identified by "aOrderBy". +** that have the same value for all columns identified by "colUsed". ** ^However omitting the extra rows is optional. ** This mode is used for a DISTINCT query. ** <li value="3"><p> ** ^(If the sqlite3_vtab_distinct() interface returns 3, that means -** that the query planner needs only distinct rows but it does need the -** rows to be sorted.)^ ^The virtual table implementation is free to omit -** rows that are identical in all aOrderBy columns, if it wants to, but +** that the query planner needs only rows that are distinct over the +** set of columns defined by "colUsed" but it does need the +** rows to be sorted according to the order defined by "aOrderBy".)^ +** ^The virtual table implementation is free to omit +** rows that are identical in all "colUsed" columns, if it wants to, but ** it is not required to omit any rows. This mode is used for queries ** that have both DISTINCT and ORDER BY clauses. ** </ol> diff --git a/src/sqliteInt.h b/src/sqliteInt.h index aa8bfc4b7..d98a4f7f0 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3312,6 +3312,7 @@ struct SrcItem { unsigned isOn :1; /* u3.pOn was once valid and non-NULL */ unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */ unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */ + unsigned rowidUsed :1; /* The ROWID of this table is referenced */ } fg; int iCursor; /* The VDBE cursor number used to access this table */ union { diff --git a/src/treeview.c b/src/treeview.c index d3346b468..fa9eac614 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -194,8 +194,10 @@ void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){ x.printfFlags |= SQLITE_PRINTF_INTERNAL; sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem); if( pItem->pTab ){ - sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx", - pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed); + sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx%s", + pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, + pItem->colUsed, + pItem->fg.rowidUsed ? "+rowid" : ""); } if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){ sqlite3_str_appendf(&x, " FULL-OUTER-JOIN"); diff --git a/src/where.c b/src/where.c index 13a362dcc..fac0f6c5e 100644 --- a/src/where.c +++ b/src/where.c @@ -1416,7 +1416,7 @@ static sqlite3_index_info *allocateIndexInfo( } if( i==n ){ nOrderBy = n; - if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) ){ + if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) && !pSrc->fg.rowidUsed ){ eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0); }else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){ eDistinct = 1; |