mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-28 08:12:28 +00:00
Upgrade SQLite to 3.40 (#699)
This commit is contained in:
parent
bcae817215
commit
0dc0758574
151 changed files with 27917 additions and 22169 deletions
344
third_party/sqlite3/pragma.c
vendored
344
third_party/sqlite3/pragma.c
vendored
|
@ -11,8 +11,7 @@
|
|||
*************************************************************************
|
||||
** This file contains code used to implement the PRAGMA command.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
|
||||
# if defined(__APPLE__)
|
||||
|
@ -308,15 +307,16 @@ static void pragmaFunclistLine(
|
|||
int isBuiltin, /* True if this is a built-in function */
|
||||
int showInternFuncs /* True if showing internal functions */
|
||||
){
|
||||
u32 mask =
|
||||
SQLITE_DETERMINISTIC |
|
||||
SQLITE_DIRECTONLY |
|
||||
SQLITE_SUBTYPE |
|
||||
SQLITE_INNOCUOUS |
|
||||
SQLITE_FUNC_INTERNAL
|
||||
;
|
||||
if( showInternFuncs ) mask = 0xffffffff;
|
||||
for(; p; p=p->pNext){
|
||||
const char *zType;
|
||||
static const u32 mask =
|
||||
SQLITE_DETERMINISTIC |
|
||||
SQLITE_DIRECTONLY |
|
||||
SQLITE_SUBTYPE |
|
||||
SQLITE_INNOCUOUS |
|
||||
SQLITE_FUNC_INTERNAL
|
||||
;
|
||||
static const char *azEnc[] = { 0, "utf8", "utf16le", "utf16be" };
|
||||
|
||||
assert( SQLITE_FUNC_ENCMASK==0x3 );
|
||||
|
@ -468,7 +468,11 @@ void sqlite3Pragma(
|
|||
|
||||
/* Locate the pragma in the lookup table */
|
||||
pPragma = pragmaLocate(zLeft);
|
||||
if( pPragma==0 ) goto pragma_out;
|
||||
if( pPragma==0 ){
|
||||
/* IMP: R-43042-22504 No error messages are generated if an
|
||||
** unknown pragma is issued. */
|
||||
goto pragma_out;
|
||||
}
|
||||
|
||||
/* Make sure the database schema is loaded if the pragma requires that */
|
||||
if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){
|
||||
|
@ -804,7 +808,7 @@ void sqlite3Pragma(
|
|||
*/
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
case PragTyp_INCREMENTAL_VACUUM: {
|
||||
int iLimit, addr;
|
||||
int iLimit = 0, addr;
|
||||
if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
|
||||
iLimit = 0x7fffffff;
|
||||
}
|
||||
|
@ -961,6 +965,7 @@ void sqlite3Pragma(
|
|||
**
|
||||
*/
|
||||
case PragTyp_TEMP_STORE_DIRECTORY: {
|
||||
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
||||
if( !zRight ){
|
||||
returnSingleText(v, sqlite3_temp_directory);
|
||||
}else{
|
||||
|
@ -970,6 +975,7 @@ void sqlite3Pragma(
|
|||
rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
|
||||
if( rc!=SQLITE_OK || res==0 ){
|
||||
sqlite3ErrorMsg(pParse, "not a writable directory");
|
||||
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
||||
goto pragma_out;
|
||||
}
|
||||
}
|
||||
|
@ -987,6 +993,7 @@ void sqlite3Pragma(
|
|||
}
|
||||
#endif /* SQLITE_OMIT_WSD */
|
||||
}
|
||||
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1005,6 +1012,7 @@ void sqlite3Pragma(
|
|||
**
|
||||
*/
|
||||
case PragTyp_DATA_STORE_DIRECTORY: {
|
||||
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
||||
if( !zRight ){
|
||||
returnSingleText(v, sqlite3_data_directory);
|
||||
}else{
|
||||
|
@ -1014,6 +1022,7 @@ void sqlite3Pragma(
|
|||
rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
|
||||
if( rc!=SQLITE_OK || res==0 ){
|
||||
sqlite3ErrorMsg(pParse, "not a writable directory");
|
||||
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
||||
goto pragma_out;
|
||||
}
|
||||
}
|
||||
|
@ -1025,6 +1034,7 @@ void sqlite3Pragma(
|
|||
}
|
||||
#endif /* SQLITE_OMIT_WSD */
|
||||
}
|
||||
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -1118,6 +1128,14 @@ void sqlite3Pragma(
|
|||
}else{
|
||||
db->flags &= ~mask;
|
||||
if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0;
|
||||
if( (mask & SQLITE_WriteSchema)!=0
|
||||
&& sqlite3_stricmp(zRight, "reset")==0
|
||||
){
|
||||
/* IMP: R-60817-01178 If the argument is "RESET" then schema
|
||||
** writing is disabled (as with "PRAGMA writable_schema=OFF") and,
|
||||
** in addition, the schema is reloaded. */
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
}
|
||||
}
|
||||
|
||||
/* Many of the flag-pragmas modify the code generated by the SQL
|
||||
|
@ -1158,6 +1176,7 @@ void sqlite3Pragma(
|
|||
sqlite3ViewGetColumnNames(pParse, pTab);
|
||||
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
|
||||
int isHidden = 0;
|
||||
const Expr *pColExpr;
|
||||
if( pCol->colFlags & COLFLAG_NOINSERT ){
|
||||
if( pPragma->iArg==0 ){
|
||||
nHidden++;
|
||||
|
@ -1178,13 +1197,16 @@ void sqlite3Pragma(
|
|||
}else{
|
||||
for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
|
||||
}
|
||||
assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN || isHidden>=2 );
|
||||
pColExpr = sqlite3ColumnExpr(pTab,pCol);
|
||||
assert( pColExpr==0 || pColExpr->op==TK_SPAN || isHidden>=2 );
|
||||
assert( pColExpr==0 || !ExprHasProperty(pColExpr, EP_IntValue)
|
||||
|| isHidden>=2 );
|
||||
sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
|
||||
i-nHidden,
|
||||
pCol->zName,
|
||||
pCol->zCnName,
|
||||
sqlite3ColumnType(pCol,""),
|
||||
pCol->notNull ? 1 : 0,
|
||||
pCol->pDflt && isHidden<2 ? pCol->pDflt->u.zToken : 0,
|
||||
(isHidden>=2 || pColExpr==0) ? 0 : pColExpr->u.zToken,
|
||||
k,
|
||||
isHidden);
|
||||
}
|
||||
|
@ -1192,6 +1214,85 @@ void sqlite3Pragma(
|
|||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
** PRAGMA table_list
|
||||
**
|
||||
** Return a single row for each table, virtual table, or view in the
|
||||
** entire schema.
|
||||
**
|
||||
** schema: Name of attached database hold this table
|
||||
** name: Name of the table itself
|
||||
** type: "table", "view", "virtual", "shadow"
|
||||
** ncol: Number of columns
|
||||
** wr: True for a WITHOUT ROWID table
|
||||
** strict: True for a STRICT table
|
||||
*/
|
||||
case PragTyp_TABLE_LIST: {
|
||||
int ii;
|
||||
pParse->nMem = 6;
|
||||
sqlite3CodeVerifyNamedSchema(pParse, zDb);
|
||||
for(ii=0; ii<db->nDb; ii++){
|
||||
HashElem *k;
|
||||
Hash *pHash;
|
||||
int initNCol;
|
||||
if( zDb && sqlite3_stricmp(zDb, db->aDb[ii].zDbSName)!=0 ) continue;
|
||||
|
||||
/* Ensure that the Table.nCol field is initialized for all views
|
||||
** and virtual tables. Each time we initialize a Table.nCol value
|
||||
** for a table, that can potentially disrupt the hash table, so restart
|
||||
** the initialization scan.
|
||||
*/
|
||||
pHash = &db->aDb[ii].pSchema->tblHash;
|
||||
initNCol = sqliteHashCount(pHash);
|
||||
while( initNCol-- ){
|
||||
for(k=sqliteHashFirst(pHash); 1; k=sqliteHashNext(k) ){
|
||||
Table *pTab;
|
||||
if( k==0 ){ initNCol = 0; break; }
|
||||
pTab = sqliteHashData(k);
|
||||
if( pTab->nCol==0 ){
|
||||
char *zSql = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName);
|
||||
if( zSql ){
|
||||
sqlite3_stmt *pDummy = 0;
|
||||
(void)sqlite3_prepare(db, zSql, -1, &pDummy, 0);
|
||||
(void)sqlite3_finalize(pDummy);
|
||||
sqlite3DbFree(db, zSql);
|
||||
}
|
||||
if( db->mallocFailed ){
|
||||
sqlite3ErrorMsg(db->pParse, "out of memory");
|
||||
db->pParse->rc = SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
pHash = &db->aDb[ii].pSchema->tblHash;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k) ){
|
||||
Table *pTab = sqliteHashData(k);
|
||||
const char *zType;
|
||||
if( zRight && sqlite3_stricmp(zRight, pTab->zName)!=0 ) continue;
|
||||
if( IsView(pTab) ){
|
||||
zType = "view";
|
||||
}else if( IsVirtual(pTab) ){
|
||||
zType = "virtual";
|
||||
}else if( pTab->tabFlags & TF_Shadow ){
|
||||
zType = "shadow";
|
||||
}else{
|
||||
zType = "table";
|
||||
}
|
||||
sqlite3VdbeMultiLoad(v, 1, "sssiii",
|
||||
db->aDb[ii].zDbSName,
|
||||
sqlite3PreferredTableName(pTab->zName),
|
||||
zType,
|
||||
pTab->nCol,
|
||||
(pTab->tabFlags & TF_WithoutRowid)!=0,
|
||||
(pTab->tabFlags & TF_Strict)!=0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
case PragTyp_STATS: {
|
||||
Index *pIdx;
|
||||
|
@ -1201,7 +1302,7 @@ void sqlite3Pragma(
|
|||
for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
|
||||
Table *pTab = sqliteHashData(i);
|
||||
sqlite3VdbeMultiLoad(v, 1, "ssiii",
|
||||
pTab->zName,
|
||||
sqlite3PreferredTableName(pTab->zName),
|
||||
0,
|
||||
pTab->szTabRow,
|
||||
pTab->nRowLogEst,
|
||||
|
@ -1251,7 +1352,7 @@ void sqlite3Pragma(
|
|||
for(i=0; i<mx; i++){
|
||||
i16 cnum = pIdx->aiColumn[i];
|
||||
sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum,
|
||||
cnum<0 ? 0 : pTab->aCol[cnum].zName);
|
||||
cnum<0 ? 0 : pTab->aCol[cnum].zCnName);
|
||||
if( pPragma->iArg ){
|
||||
sqlite3VdbeMultiLoad(v, 4, "isiX",
|
||||
pIdx->aSortOrder[i],
|
||||
|
@ -1320,11 +1421,13 @@ void sqlite3Pragma(
|
|||
pParse->nMem = 6;
|
||||
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
|
||||
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
|
||||
assert( p->funcFlags & SQLITE_FUNC_BUILTIN );
|
||||
pragmaFunclistLine(v, p, 1, showInternFunc);
|
||||
}
|
||||
}
|
||||
for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){
|
||||
p = (FuncDef*)sqliteHashData(j);
|
||||
assert( (p->funcFlags & SQLITE_FUNC_BUILTIN)==0 );
|
||||
pragmaFunclistLine(v, p, 0, showInternFunc);
|
||||
}
|
||||
}
|
||||
|
@ -1358,8 +1461,8 @@ void sqlite3Pragma(
|
|||
FKey *pFK;
|
||||
Table *pTab;
|
||||
pTab = sqlite3FindTable(db, zRight, zDb);
|
||||
if( pTab ){
|
||||
pFK = pTab->pFKey;
|
||||
if( pTab && IsOrdinaryTable(pTab) ){
|
||||
pFK = pTab->u.tab.pFKey;
|
||||
if( pFK ){
|
||||
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
int i = 0;
|
||||
|
@ -1372,7 +1475,7 @@ void sqlite3Pragma(
|
|||
i,
|
||||
j,
|
||||
pFK->zTo,
|
||||
pTab->aCol[pFK->aCol[j].iFrom].zName,
|
||||
pTab->aCol[pFK->aCol[j].iFrom].zCnName,
|
||||
pFK->aCol[j].zCol,
|
||||
actionName(pFK->aAction[1]), /* ON UPDATE */
|
||||
actionName(pFK->aAction[0]), /* ON DELETE */
|
||||
|
@ -1399,7 +1502,6 @@ void sqlite3Pragma(
|
|||
HashElem *k; /* Loop counter: Next table in schema */
|
||||
int x; /* result variable */
|
||||
int regResult; /* 3 registers to hold a result row */
|
||||
int regKey; /* Register to hold key for checking the FK */
|
||||
int regRow; /* Registers to hold a row from pTab */
|
||||
int addrTop; /* Top of a loop checking foreign keys */
|
||||
int addrOk; /* Jump here if the key is OK */
|
||||
|
@ -1407,7 +1509,6 @@ void sqlite3Pragma(
|
|||
|
||||
regResult = pParse->nMem+1;
|
||||
pParse->nMem += 4;
|
||||
regKey = ++pParse->nMem;
|
||||
regRow = ++pParse->nMem;
|
||||
k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
|
||||
while( k ){
|
||||
|
@ -1418,7 +1519,7 @@ void sqlite3Pragma(
|
|||
pTab = (Table*)sqliteHashData(k);
|
||||
k = sqliteHashNext(k);
|
||||
}
|
||||
if( pTab==0 || pTab->pFKey==0 ) continue;
|
||||
if( pTab==0 || !IsOrdinaryTable(pTab) || pTab->u.tab.pFKey==0 ) continue;
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
zDb = db->aDb[iDb].zDbSName;
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
|
@ -1426,7 +1527,8 @@ void sqlite3Pragma(
|
|||
if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
|
||||
sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
|
||||
sqlite3VdbeLoadString(v, regResult, pTab->zName);
|
||||
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
|
||||
assert( IsOrdinaryTable(pTab) );
|
||||
for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
|
||||
pParent = sqlite3FindTable(db, pFK->zTo, zDb);
|
||||
if( pParent==0 ) continue;
|
||||
pIdx = 0;
|
||||
|
@ -1448,7 +1550,8 @@ void sqlite3Pragma(
|
|||
if( pFK ) break;
|
||||
if( pParse->nTab<i ) pParse->nTab = i;
|
||||
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v);
|
||||
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
|
||||
assert( IsOrdinaryTable(pTab) );
|
||||
for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
|
||||
pParent = sqlite3FindTable(db, pFK->zTo, zDb);
|
||||
pIdx = 0;
|
||||
aiCols = 0;
|
||||
|
@ -1462,6 +1565,7 @@ void sqlite3Pragma(
|
|||
** regRow..regRow+n. If any of the child key values are NULL, this
|
||||
** row cannot cause an FK violation. Jump directly to addrOk in
|
||||
** this case. */
|
||||
if( regRow+pFK->nCol>pParse->nMem ) pParse->nMem = regRow+pFK->nCol;
|
||||
for(j=0; j<pFK->nCol; j++){
|
||||
int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom;
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j);
|
||||
|
@ -1471,9 +1575,9 @@ void sqlite3Pragma(
|
|||
/* Generate code to query the parent index for a matching parent
|
||||
** key. If a match is found, jump to addrOk. */
|
||||
if( pIdx ){
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey,
|
||||
sqlite3VdbeAddOp4(v, OP_Affinity, regRow, pFK->nCol, 0,
|
||||
sqlite3IndexAffinityStr(db,pIdx), pFK->nCol);
|
||||
sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
|
||||
sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regRow, pFK->nCol);
|
||||
VdbeCoverage(v);
|
||||
}else if( pParent ){
|
||||
int jmp = sqlite3VdbeCurrentAddr(v)+2;
|
||||
|
@ -1644,14 +1748,24 @@ void sqlite3Pragma(
|
|||
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
|
||||
Table *pTab = sqliteHashData(x);
|
||||
Index *pIdx, *pPk;
|
||||
Index *pPrior = 0;
|
||||
Index *pPrior = 0; /* Previous index */
|
||||
int loopTop;
|
||||
int iDataCur, iIdxCur;
|
||||
int r1 = -1;
|
||||
int bStrict; /* True for a STRICT table */
|
||||
int r2; /* Previous key for WITHOUT ROWID tables */
|
||||
int mxCol; /* Maximum non-virtual column number */
|
||||
|
||||
if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
|
||||
if( !IsOrdinaryTable(pTab) ) continue;
|
||||
if( pObjTab && pObjTab!=pTab ) continue;
|
||||
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||
if( isQuick || HasRowid(pTab) ){
|
||||
pPk = 0;
|
||||
r2 = 0;
|
||||
}else{
|
||||
pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
r2 = sqlite3GetTempRange(pParse, pPk->nKeyCol);
|
||||
sqlite3VdbeAddOp3(v, OP_Null, 1, r2, r2+pPk->nKeyCol-1);
|
||||
}
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
|
||||
1, 0, &iDataCur, &iIdxCur);
|
||||
/* reg[7] counts the number of entries in the table.
|
||||
|
@ -1665,27 +1779,157 @@ void sqlite3Pragma(
|
|||
assert( sqlite3NoTempsInRange(pParse,1,7+j) );
|
||||
sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
|
||||
loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
|
||||
if( !isQuick ){
|
||||
/* Sanity check on record header decoding */
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nNVCol-1,3);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
|
||||
|
||||
/* Fetch the right-most column from the table. This will cause
|
||||
** the entire record header to be parsed and sanity checked. It
|
||||
** will also prepopulate the cursor column cache that is used
|
||||
** by the OP_IsType code, so it is a required step.
|
||||
*/
|
||||
mxCol = pTab->nCol-1;
|
||||
while( mxCol>=0
|
||||
&& ((pTab->aCol[mxCol].colFlags & COLFLAG_VIRTUAL)!=0
|
||||
|| pTab->iPKey==mxCol) ) mxCol--;
|
||||
if( mxCol>=0 ){
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, mxCol, 3);
|
||||
sqlite3VdbeTypeofColumn(v, 3);
|
||||
}
|
||||
/* Verify that all NOT NULL columns really are NOT NULL */
|
||||
|
||||
if( !isQuick ){
|
||||
if( pPk ){
|
||||
/* Verify WITHOUT ROWID keys are in ascending order */
|
||||
int a1;
|
||||
char *zErr;
|
||||
a1 = sqlite3VdbeAddOp4Int(v, OP_IdxGT, iDataCur, 0,r2,pPk->nKeyCol);
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp1(v, OP_IsNull, r2); VdbeCoverage(v);
|
||||
zErr = sqlite3MPrintf(db,
|
||||
"row not in PRIMARY KEY order for %s",
|
||||
pTab->zName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, a1);
|
||||
sqlite3VdbeJumpHere(v, a1+1);
|
||||
for(j=0; j<pPk->nKeyCol; j++){
|
||||
sqlite3ExprCodeLoadIndexColumn(pParse, pPk, iDataCur, j, r2+j);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Verify datatypes for all columns:
|
||||
**
|
||||
** (1) NOT NULL columns may not contain a NULL
|
||||
** (2) Datatype must be exact for non-ANY columns in STRICT tables
|
||||
** (3) Datatype for TEXT columns in non-STRICT tables must be
|
||||
** NULL, TEXT, or BLOB.
|
||||
** (4) Datatype for numeric columns in non-STRICT tables must not
|
||||
** be a TEXT value that can be losslessly converted to numeric.
|
||||
*/
|
||||
bStrict = (pTab->tabFlags & TF_Strict)!=0;
|
||||
for(j=0; j<pTab->nCol; j++){
|
||||
char *zErr;
|
||||
int jmp2;
|
||||
Column *pCol = pTab->aCol + j; /* The column to be checked */
|
||||
int labelError; /* Jump here to report an error */
|
||||
int labelOk; /* Jump here if all looks ok */
|
||||
int p1, p3, p4; /* Operands to the OP_IsType opcode */
|
||||
int doTypeCheck; /* Check datatypes (besides NOT NULL) */
|
||||
|
||||
if( j==pTab->iPKey ) continue;
|
||||
if( pTab->aCol[j].notNull==0 ) continue;
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
|
||||
if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
|
||||
if( bStrict ){
|
||||
doTypeCheck = pCol->eCType>COLTYPE_ANY;
|
||||
}else{
|
||||
doTypeCheck = pCol->affinity>SQLITE_AFF_BLOB;
|
||||
}
|
||||
jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
|
||||
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
|
||||
pTab->aCol[j].zName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
if( pCol->notNull==0 && !doTypeCheck ) continue;
|
||||
|
||||
/* Compute the operands that will be needed for OP_IsType */
|
||||
p4 = SQLITE_NULL;
|
||||
if( pCol->colFlags & COLFLAG_VIRTUAL ){
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
|
||||
p1 = -1;
|
||||
p3 = 3;
|
||||
}else{
|
||||
if( pCol->iDflt ){
|
||||
sqlite3_value *pDfltValue = 0;
|
||||
sqlite3ValueFromExpr(db, sqlite3ColumnExpr(pTab,pCol), ENC(db),
|
||||
pCol->affinity, &pDfltValue);
|
||||
if( pDfltValue ){
|
||||
p4 = sqlite3_value_type(pDfltValue);
|
||||
sqlite3ValueFree(pDfltValue);
|
||||
}
|
||||
}
|
||||
p1 = iDataCur;
|
||||
if( !HasRowid(pTab) ){
|
||||
testcase( j!=sqlite3TableColumnToStorage(pTab, j) );
|
||||
p3 = sqlite3TableColumnToIndex(sqlite3PrimaryKeyIndex(pTab), j);
|
||||
}else{
|
||||
p3 = sqlite3TableColumnToStorage(pTab,j);
|
||||
testcase( p3!=j);
|
||||
}
|
||||
}
|
||||
|
||||
labelError = sqlite3VdbeMakeLabel(pParse);
|
||||
labelOk = sqlite3VdbeMakeLabel(pParse);
|
||||
if( pCol->notNull ){
|
||||
/* (1) NOT NULL columns may not contain a NULL */
|
||||
int jmp2 = sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
|
||||
sqlite3VdbeChangeP5(v, 0x0f);
|
||||
VdbeCoverage(v);
|
||||
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
|
||||
pCol->zCnName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
if( doTypeCheck ){
|
||||
sqlite3VdbeGoto(v, labelError);
|
||||
sqlite3VdbeJumpHere(v, jmp2);
|
||||
}else{
|
||||
/* VDBE byte code will fall thru */
|
||||
}
|
||||
}
|
||||
if( bStrict && doTypeCheck ){
|
||||
/* (2) Datatype must be exact for non-ANY columns in STRICT tables*/
|
||||
static unsigned char aStdTypeMask[] = {
|
||||
0x1f, /* ANY */
|
||||
0x18, /* BLOB */
|
||||
0x11, /* INT */
|
||||
0x11, /* INTEGER */
|
||||
0x13, /* REAL */
|
||||
0x14 /* TEXT */
|
||||
};
|
||||
sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
|
||||
assert( pCol->eCType>=1 && pCol->eCType<=sizeof(aStdTypeMask) );
|
||||
sqlite3VdbeChangeP5(v, aStdTypeMask[pCol->eCType-1]);
|
||||
VdbeCoverage(v);
|
||||
zErr = sqlite3MPrintf(db, "non-%s value in %s.%s",
|
||||
sqlite3StdType[pCol->eCType-1],
|
||||
pTab->zName, pTab->aCol[j].zCnName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
}else if( !bStrict && pCol->affinity==SQLITE_AFF_TEXT ){
|
||||
/* (3) Datatype for TEXT columns in non-STRICT tables must be
|
||||
** NULL, TEXT, or BLOB. */
|
||||
sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
|
||||
sqlite3VdbeChangeP5(v, 0x1c); /* NULL, TEXT, or BLOB */
|
||||
VdbeCoverage(v);
|
||||
zErr = sqlite3MPrintf(db, "NUMERIC value in %s.%s",
|
||||
pTab->zName, pTab->aCol[j].zCnName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
}else if( !bStrict && pCol->affinity>=SQLITE_AFF_NUMERIC ){
|
||||
/* (4) Datatype for numeric columns in non-STRICT tables must not
|
||||
** be a TEXT value that can be converted to numeric. */
|
||||
sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
|
||||
sqlite3VdbeChangeP5(v, 0x1b); /* NULL, INT, FLOAT, or BLOB */
|
||||
VdbeCoverage(v);
|
||||
if( p1>=0 ){
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, OP_Affinity, 3, 1, 0, "C", P4_STATIC);
|
||||
sqlite3VdbeAddOp4Int(v, OP_IsType, -1, labelOk, 3, p4);
|
||||
sqlite3VdbeChangeP5(v, 0x1c); /* NULL, TEXT, or BLOB */
|
||||
VdbeCoverage(v);
|
||||
zErr = sqlite3MPrintf(db, "TEXT value in %s.%s",
|
||||
pTab->zName, pTab->aCol[j].zCnName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
}
|
||||
sqlite3VdbeResolveLabel(v, labelError);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, jmp2);
|
||||
sqlite3VdbeResolveLabel(v, labelOk);
|
||||
}
|
||||
/* Verify CHECK constraints */
|
||||
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
|
||||
|
@ -1773,6 +2017,9 @@ void sqlite3Pragma(
|
|||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
}
|
||||
if( pPk ){
|
||||
sqlite3ReleaseTempRange(pParse, r2, pPk->nKeyCol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1923,6 +2170,11 @@ void sqlite3Pragma(
|
|||
aOp[1].p2 = iCookie;
|
||||
aOp[1].p3 = sqlite3Atoi(zRight);
|
||||
aOp[1].p5 = 1;
|
||||
if( iCookie==BTREE_SCHEMA_VERSION && (db->flags & SQLITE_Defensive)!=0 ){
|
||||
/* Do not allow the use of PRAGMA schema_version=VALUE in defensive
|
||||
** mode. Change the OP_SetCookie opcode into a no-op. */
|
||||
aOp[1].opcode = OP_Noop;
|
||||
}
|
||||
}else{
|
||||
/* Read the specified cookie value */
|
||||
static const VdbeOpList readCookie[] = {
|
||||
|
@ -2219,12 +2471,12 @@ void sqlite3Pragma(
|
|||
case PragTyp_ANALYSIS_LIMIT: {
|
||||
sqlite3_int64 N;
|
||||
if( zRight
|
||||
&& sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK
|
||||
&& sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK /* IMP: R-40975-20399 */
|
||||
&& N>=0
|
||||
){
|
||||
db->nAnalysisLimit = (int)(N&0x7fffffff);
|
||||
}
|
||||
returnSingleInt(v, db->nAnalysisLimit);
|
||||
returnSingleInt(v, db->nAnalysisLimit); /* IMP: R-57594-65522 */
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue