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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user