mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
When compiled with SQLITE_ALLOW_ROWID_IN_VIEW, rowid-in-view is on by default
but can now be turned off using SQLITE_TESTCTRL_ROWID_IN_VIEW. Without the compile-time option, rowid-in-view is always off. FossilOrigin-Name: 8a6196ab29052071be753c5c77ac945c2d62ecc8019c6160f954eafe34ab05a8
This commit is contained in:
@@ -3006,9 +3006,12 @@ void sqlite3CreateView(
|
||||
** on a view, even though views do not have rowids. The following flag
|
||||
** setting fixes this problem. But the fix can be disabled by compiling
|
||||
** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that
|
||||
** depend upon the old buggy behavior. */
|
||||
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
p->tabFlags |= TF_NoVisibleRowid;
|
||||
** depend upon the old buggy behavior. The ability can also be toggled
|
||||
** using SQLITE_TESTCTRL_ROWID_IN_VIEW */
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
p->tabFlags |= sqlite3Config.mNoVisibleRowid; /* Optional. Allow by default */
|
||||
#else
|
||||
p->tabFlags |= TF_NoVisibleRowid; /* Never allow rowid in view */
|
||||
#endif
|
||||
|
||||
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
|
||||
|
@@ -288,6 +288,9 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
#endif
|
||||
#ifndef SQLITE_UNTESTABLE
|
||||
0, /* xTestCallback */
|
||||
#endif
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
0, /* mNoVisibleRowid. 0 == allow rowid-in-view */
|
||||
#endif
|
||||
0, /* bLocaltimeFault */
|
||||
0, /* xAltLocaltime */
|
||||
|
33
src/main.c
33
src/main.c
@@ -4405,6 +4405,39 @@ int sqlite3_test_control(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_ROWID_IN_VIEW, int *pVal);
|
||||
**
|
||||
** Query or set the sqlite3Config.mNoVisibleRowid flag. Cases:
|
||||
**
|
||||
** *pVal==1 Allow ROWID in VIEWs
|
||||
** *pVal==0 Disallow ROWID in VIEWs
|
||||
** *pVal<0 No change
|
||||
**
|
||||
** In every case *pVal is written with 1 if ROWID is allowd in VIEWs and
|
||||
** 0 if not. Changes to the setting only occur if SQLite is compiled
|
||||
** with -DSQLITE_ALLOW_ROWID_IN_VIEW (hereafter: "SARIV"). With the
|
||||
** "SARIV" compile-time option the default value for this setting is 1.
|
||||
** Otherwise this setting defaults to 0. This setting may only be changed
|
||||
** if SQLite is compiled with "SARIV". Hence, in the normal case when
|
||||
** SQLite is compiled without "SARIV", this test-control is a no-op
|
||||
** that always leaves *pVal set to 0.
|
||||
**
|
||||
** IMPORTANT: If you change this setting while a database connection
|
||||
** is option, it is very important to run "PRAGMA writable_schema=RESET"
|
||||
** afterwards in order to reparse all VIEW definitions in the schema.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_ROWID_IN_VIEW: {
|
||||
int *pVal = va_arg(ap, int*);
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
if( *pVal==0 ) sqlite3Config.mNoVisibleRowid = TF_NoVisibleRowid;
|
||||
if( *pVal==1 ) sqlite3Config.mNoVisibleRowid = 0;
|
||||
*pVal = (sqlite3Config.mNoVisibleRowid==0);
|
||||
#else
|
||||
*pVal = 0;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, sqlite3*);
|
||||
**
|
||||
** Toggle the ability to use internal functions on or off for
|
||||
|
22
src/select.c
22
src/select.c
@@ -1953,11 +1953,7 @@ static const char *columnTypeImpl(
|
||||
** data for the result-set column of the sub-select.
|
||||
*/
|
||||
if( iCol<pS->pEList->nExpr
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
&& iCol>=0
|
||||
#else
|
||||
&& ALWAYS(iCol>=0)
|
||||
#endif
|
||||
&& (!ViewCanHaveRowid || iCol>=0)
|
||||
){
|
||||
/* If iCol is less than zero, then the expression requests the
|
||||
** rowid of the sub-select or view. This expression is legal (see
|
||||
@@ -5874,7 +5870,8 @@ int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
|
||||
/* The usual case - do not allow ROWID on a subquery */
|
||||
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
|
||||
#else
|
||||
pTab->tabFlags |= TF_Ephemeral; /* Legacy compatibility mode */
|
||||
/* Legacy compatibility mode */
|
||||
pTab->tabFlags |= TF_Ephemeral | sqlite3Config.mNoVisibleRowid;
|
||||
#endif
|
||||
return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
|
||||
}
|
||||
@@ -6142,9 +6139,7 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
pNestedFrom = pFrom->pSelect->pEList;
|
||||
assert( pNestedFrom!=0 );
|
||||
assert( pNestedFrom->nExpr==pTab->nCol );
|
||||
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
assert( VisibleRowid(pTab)==0 );
|
||||
#endif
|
||||
assert( VisibleRowid(pTab)==0 || ViewCanHaveRowid );
|
||||
}else{
|
||||
if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
|
||||
continue;
|
||||
@@ -6177,9 +6172,12 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
}
|
||||
|
||||
nAdd = pTab->nCol;
|
||||
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
if( VisibleRowid(pTab) && (selFlags & SF_NestedFrom)!=0 ) nAdd++;
|
||||
#endif
|
||||
if( VisibleRowid(pTab)
|
||||
&& !ViewCanHaveRowid
|
||||
&& (selFlags & SF_NestedFrom)!=0
|
||||
){
|
||||
nAdd++;
|
||||
}
|
||||
for(j=0; j<nAdd; j++){
|
||||
const char *zName;
|
||||
struct ExprList_item *pX; /* Newly added ExprList term */
|
||||
|
@@ -10893,6 +10893,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
{"prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
|
||||
{"prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
|
||||
{"prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
|
||||
{"rowid_in_view", SQLITE_TESTCTRL_ROWID_IN_VIEW,0,"?BOOLEAN?" },
|
||||
{"seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
|
||||
{"sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
|
||||
{"tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" },
|
||||
@@ -11067,6 +11068,20 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case SQLITE_TESTCTRL_ROWID_IN_VIEW: {
|
||||
rc2 = -1;
|
||||
if( nArg>=3 ){
|
||||
if( !ShellHasFlag(p,SHFLG_TestingMode) ){
|
||||
eputz("The --unsafe-testing option is required to change "
|
||||
"this setting\n");
|
||||
}else{
|
||||
rc2 = booleanValue(azArg[2]);
|
||||
}
|
||||
}
|
||||
sqlite3_test_control(testctrl, &rc2);
|
||||
isOk = 1;
|
||||
break;
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
case SQLITE_TESTCTRL_TUNE: {
|
||||
if( nArg==4 ){
|
||||
|
@@ -8307,6 +8307,7 @@ int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_JSON_SELFCHECK 14
|
||||
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
|
||||
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_ROWID_IN_VIEW 16
|
||||
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
|
||||
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
|
||||
|
@@ -2535,6 +2535,15 @@ struct Table {
|
||||
#define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0)
|
||||
#define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0)
|
||||
|
||||
/* Macro is true if the SQLITE_ALLOW_ROWID_IN_VIEW (mis-)feature is
|
||||
** available. By default, this macro is false
|
||||
*/
|
||||
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
# define ViewCanHaveRowid 0
|
||||
#else
|
||||
# define ViewCanHaveRowid (sqlite3Config.mNoVisibleRowid==0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Each foreign key constraint is an instance of the following structure.
|
||||
**
|
||||
@@ -4253,6 +4262,11 @@ struct Sqlite3Config {
|
||||
#endif
|
||||
#ifndef SQLITE_UNTESTABLE
|
||||
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
|
||||
#endif
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
u32 mNoVisibleRowid; /* TF_NoVisibleRowid if the ROWID_IN_VIEW
|
||||
** feature is disabled. 0 if rowids can
|
||||
** occur in views. */
|
||||
#endif
|
||||
int bLocaltimeFault; /* True to fail localtime() calls */
|
||||
int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */
|
||||
|
Reference in New Issue
Block a user