Fix the UPDATE-FROM logic so that it works the same as PostgreSQL when the

FROM clause contains an outer join.

FossilOrigin-Name: 98b3816bbaf539ea745456e1c0064e47d2903d33ee0ceb029bdb97d56fcde937
This commit is contained in:
drh
2022-05-25 11:09:07 +00:00
5 changed files with 107 additions and 19 deletions
+12 -1
View File
@@ -940,7 +940,18 @@ cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y) from(F)
where_opt_ret(W). {
sqlite3SrcListIndexedBy(pParse, X, &I);
sqlite3ExprListCheckLength(pParse,Y,"set list");
X = sqlite3SrcListAppendList(pParse, X, F);
if( F ){
SrcList *pFromClause = F;
if( pFromClause->nSrc>1 ){
Select *pSubquery;
Token as;
pSubquery = sqlite3SelectNew(pParse,0,pFromClause,0,0,0,0,SF_NestedFrom,0);
as.n = 0;
as.z = 0;
pFromClause = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0);
}
X = sqlite3SrcListAppendList(pParse, X, pFromClause);
}
sqlite3Update(pParse,X,Y,W,R,0,0,0);
}
%endif
+29 -9
View File
@@ -6518,6 +6518,29 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
}
#endif /* SQLITE_COUNTOFVIEW_OPTIMIZATION */
/*
** If any term of pSrc, or any SF_NestedFrom sub-query, is not the same
** as pSrcItem but has the same alias as p0, then return true.
** Otherwise return false.
*/
static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){
int i;
for(i=0; i<pSrc->nSrc; i++){
SrcItem *p1 = &pSrc->a[i];
if( p1==p0 ) continue;
if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
return 1;
}
if( p1->pSelect
&& (p1->pSelect->selFlags & SF_NestedFrom)!=0
&& sameSrcAlias(p0, p1->pSelect->pSrc)
){
return 1;
}
}
return 0;
}
/*
** Generate code for the SELECT statement given in the p argument.
**
@@ -6622,15 +6645,12 @@ int sqlite3Select(
** disallow it altogether. */
if( p->selFlags & SF_UFSrcCheck ){
SrcItem *p0 = &p->pSrc->a[0];
for(i=1; i<p->pSrc->nSrc; i++){
SrcItem *p1 = &p->pSrc->a[i];
if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
sqlite3ErrorMsg(pParse,
"target object/alias may not appear in FROM clause: %s",
p0->zAlias ? p0->zAlias : p0->pTab->zName
);
goto select_end;
}
if( sameSrcAlias(p0, p->pSrc) ){
sqlite3ErrorMsg(pParse,
"target object/alias may not appear in FROM clause: %s",
p0->zAlias ? p0->zAlias : p0->pTab->zName
);
goto select_end;
}
/* Clear the SF_UFSrcCheck flag. The check has already been performed,