diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/insert.c | 18 | ||||
-rw-r--r-- | src/sqliteInt.h | 1 | ||||
-rw-r--r-- | src/vdbe.c | 12 | ||||
-rw-r--r-- | src/vdbe.h | 5 | ||||
-rw-r--r-- | src/vdbeaux.c | 2 |
5 files changed, 34 insertions, 4 deletions
diff --git a/src/insert.c b/src/insert.c index 93c22ae3f..5bb8ba2ff 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1669,6 +1669,23 @@ void sqlite3GenerateConstraintChecks( } /* +** Change the P5 operand on the last opcode (which should be an OP_MakeRecord) +** to be the number of columns in table pTab that must not be NULL-trimmed. +** +** Or if no columns of pTab may be NULL-trimmed, leave P5 at zero. +*/ +void sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){ + u16 i; + + /* Records with omitted columns are only allowed for schema format + ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */ + if( pTab->pSchema->file_format<2 ) return; + + for(i=pTab->nCol; i>1 && pTab->aCol[i-1].pDflt==0; i--){} + sqlite3VdbeChangeP5(v, i); +} + +/* ** This routine generates code to finish the INSERT or UPDATE operation ** that was started by a prior call to sqlite3GenerateConstraintChecks. ** A consecutive range of registers starting at regNewData contains the @@ -1727,6 +1744,7 @@ void sqlite3CompleteInsertion( regData = regNewData + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); + sqlite3SetMakeRecordP5(v, pTab); if( !bAffinityDone ){ sqlite3TableAffinity(v, pTab, 0); sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 6344cac5f..ceae4dcb1 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3790,6 +3790,7 @@ int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); void sqlite3ResolvePartIdxLabel(Parse*,int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, u8,u8,int,int*,int*); +void sqlite3SetMakeRecordP5(Vdbe*,Table*); void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int); int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*); void sqlite3BeginWriteOperation(Parse*, int, int); diff --git a/src/vdbe.c b/src/vdbe.c index cbb786751..88010a9a6 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2777,6 +2777,18 @@ case OP_MakeRecord: { }while( zAffinity[0] ); } + /* NULLs can be safely trimmed from the end of the record, as long as + ** as the schema format is 2 or more and none of the omitted columns + ** have a non-NULL default value. Also, the record must be left with + ** at least one field. If P5>0 then it will be one more than the + ** index of the right-most column with a non-NULL default value */ + if( pOp->p5 ){ + while( (pLast->flags & MEM_Null)!=0 && nField>pOp->p5 ){ + pLast--; + nField--; + } + } + /* Loop through the elements that will make up the record to figure ** out how much space is required for the new record. */ diff --git a/src/vdbe.h b/src/vdbe.h index feaf11680..a35f3be34 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -41,8 +41,7 @@ typedef struct SubProgram SubProgram; struct VdbeOp { u8 opcode; /* What operation to perform */ signed char p4type; /* One of the P4_xxx constants for p4 */ - u8 notUsed1; - u8 p5; /* Fifth parameter is an unsigned character */ + u16 p5; /* Fifth parameter is an unsigned 16-bit integer */ int p1; /* First operand */ int p2; /* Second parameter (often the jump destination) */ int p3; /* The third parameter */ @@ -194,7 +193,7 @@ void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8); void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); -void sqlite3VdbeChangeP5(Vdbe*, u8 P5); +void sqlite3VdbeChangeP5(Vdbe*, u16 P5); void sqlite3VdbeJumpHere(Vdbe*, int addr); int sqlite3VdbeChangeToNoop(Vdbe*, int addr); int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 85d273f1e..cd423ed5b 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -783,7 +783,7 @@ void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){ void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){ sqlite3VdbeGetOp(p,addr)->p3 = val; } -void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){ +void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){ assert( p->nOp>0 || p->db->mallocFailed ); if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5; } |