1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-12-03 08:01:19 +03:00

Merge trunk enhancements into the generated-columns branch.

FossilOrigin-Name: 85bc4524d76999080faa4474e8880d2b6a2ac3a7f6a76239af4de1a42f8138c8
This commit is contained in:
drh
2019-10-18 17:47:47 +00:00
10 changed files with 172 additions and 38 deletions

View File

@@ -1680,6 +1680,8 @@ void sqlite3GenerateConstraintChecks(
sqlite3MultiWrite(pParse);
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
regNewData, 1, 0, OE_Replace, 1, -1);
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
sqlite3RowidConstraint(pParse, OE_Abort, pTab);
}else{
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
assert( HasRowid(pTab) );
@@ -1934,16 +1936,23 @@ void sqlite3GenerateConstraintChecks(
}
default: {
Trigger *pTrigger = 0;
int bRetryConstraintCheck = 0;
assert( onError==OE_Replace );
if( db->flags&SQLITE_RecTriggers ){
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
}
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
sqlite3MultiWrite(pParse);
bRetryConstraintCheck = 1;
}
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
regR, nPkField, 0, OE_Replace,
(pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
if( bRetryConstraintCheck ){
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
sqlite3UniqueConstraint(pParse, OE_Abort, pIdx);
}
seenReplace = 1;
break;
}

View File

@@ -7758,10 +7758,19 @@ static int do_meta_command(char *zLine, ShellState *p){
char *zCollist = 0;
sqlite3_stmt *pStmt;
int tnum = 0;
int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
int i;
if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
" .imposter off\n");
/* Also allowed, but not documented:
**
** .imposter TABLE IMPOSTER
**
** where TABLE is a WITHOUT ROWID table. In that case, the
** imposter is another WITHOUT ROWID table with the columns in
** storage order. */
rc = 1;
goto meta_command_exit;
}
@@ -7770,19 +7779,22 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
goto meta_command_exit;
}
zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master"
" WHERE name='%q' AND type='index'", azArg[1]);
zSql = sqlite3_mprintf(
"SELECT rootpage, 0 FROM sqlite_master"
" WHERE name='%q' AND type='index'"
"UNION ALL "
"SELECT rootpage, 1 FROM sqlite_master"
" WHERE name='%q' AND type='table'"
" AND sql LIKE '%%without%%rowid%%'",
azArg[1], azArg[1]
);
sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
tnum = sqlite3_column_int(pStmt, 0);
isWO = sqlite3_column_int(pStmt, 1);
}
sqlite3_finalize(pStmt);
if( tnum==0 ){
utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
rc = 1;
goto meta_command_exit;
}
zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
@@ -7799,6 +7811,9 @@ static int do_meta_command(char *zLine, ShellState *p){
zCol = zLabel;
}
}
if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
lenPK = (int)strlen(zCollist);
}
if( zCollist==0 ){
zCollist = sqlite3_mprintf("\"%w\"", zCol);
}else{
@@ -7806,9 +7821,16 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}
sqlite3_finalize(pStmt);
if( i==0 || tnum==0 ){
utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
rc = 1;
sqlite3_free(zCollist);
goto meta_command_exit;
}
if( lenPK==0 ) lenPK = 100000;
zSql = sqlite3_mprintf(
"CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID",
azArg[2], zCollist, zCollist);
"CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
azArg[2], zCollist, lenPK, zCollist);
sqlite3_free(zCollist);
rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
if( rc==SQLITE_OK ){
@@ -7819,7 +7841,8 @@ static int do_meta_command(char *zLine, ShellState *p){
}else{
utf8_printf(stdout, "%s;\n", zSql);
raw_printf(stdout,
"WARNING: writing to an imposter table will corrupt the index!\n"
"WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
azArg[1], isWO ? "table" : "index"
);
}
}else{

View File

@@ -757,7 +757,7 @@ char *sqlite3Normalize(
int nParen; /* Number of nested levels of parentheses */
int iStartIN; /* Start of RHS of IN operator in z[] */
int nParenAtIN; /* Value of nParent at start of RHS of IN operator */
int j; /* Bytes of normalized SQL generated so far */
u32 j; /* Bytes of normalized SQL generated so far */
sqlite3_str *pStr; /* The normalized SQL string under construction */
db = sqlite3VdbeDb(pVdbe);
@@ -801,7 +801,7 @@ char *sqlite3Normalize(
}
case TK_RP: {
if( iStartIN>0 && nParen==nParenAtIN ){
assert( pStr->nChar>=iStartIN );
assert( pStr->nChar>=(u32)iStartIN );
pStr->nChar = iStartIN+1;
sqlite3_str_append(pStr, "?,?,?", 5);
iStartIN = 0;

View File

@@ -289,6 +289,10 @@ void sqlite3Update(
sNC.uNC.pUpsert = pUpsert;
sNC.ncFlags = NC_UUpsert;
/* Begin generating code. */
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto update_cleanup;
/* Resolve the column names in all the expressions of the
** of the UPDATE statement. Also find the column index
** for each column to be updated in the pChanges array. For each
@@ -394,9 +398,6 @@ void sqlite3Update(
memset(aToOpen, 1, nIdx+1);
}
/* Begin generating code. */
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto update_cleanup;
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb);