/ Check-in [96269f01]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Simplifications to the SQLITE_KEEPNULL flag on VDBE comparison operators.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | rowvalue
Files: files | file ages | folders
SHA1: 96269f0179a7d8fa44ee278cef362962368c59ef
User & Date: drh 2016-09-05 15:02:41
Context
2016-09-05
19:57
Fix an assert() so that it does C-compiler does not combine an assert() conditional with a production code conditional and thereby confuse the mutation testing script. check-in: 2fa5288a user: drh tags: rowvalue
15:02
Simplifications to the SQLITE_KEEPNULL flag on VDBE comparison operators. check-in: 96269f01 user: drh tags: rowvalue
12:12
Do vector comparison size checking early - at name resolution time - to forestall future problems. check-in: ae127bcc user: drh tags: rowvalue
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

  1908   1908   ** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
  1909   1909   ** true or false and is never NULL.  If both operands are NULL then the result
  1910   1910   ** of comparison is true.  If either operand is NULL then the result is false.
  1911   1911   ** If neither operand is NULL the result is the same as it would be if
  1912   1912   ** the SQLITE_NULLEQ flag were omitted from P5.
  1913   1913   **
  1914   1914   ** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
  1915         -** content of r[P2] is only set to 1 (true) if it was not previously NULL.
         1915  +** content of r[P2] is only changed if the new value is NULL or 0 (false).
         1916  +** In other words, a prior r[P2] value will not be overwritten by 1 (true).
  1916   1917   */
  1917   1918   /* Opcode: Ne P1 P2 P3 P4 P5
  1918   1919   ** Synopsis: IF r[P3]!=r[P1]
  1919   1920   **
  1920   1921   ** This works just like the Eq opcode except that the jump is taken if
  1921   1922   ** the operands in registers P1 and P3 are not equal.  See the Eq opcode for
  1922   1923   ** additional information.
  1923   1924   **
  1924   1925   ** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
  1925         -** content of r[P2] is only set to 0 (false) if it was not previously NULL.
         1926  +** content of r[P2] is only changed if the new value is NULL or 1 (true).
         1927  +** In other words, a prior r[P2] value will not be overwritten by 0 (false).
  1926   1928   */
  1927   1929   /* Opcode: Lt P1 P2 P3 P4 P5
  1928   1930   ** Synopsis: IF r[P3]<r[P1]
  1929   1931   **
  1930   1932   ** Compare the values in register P1 and P3.  If reg(P3)<reg(P1) then
  1931   1933   ** jump to address P2.  Or if the SQLITE_STOREP2 flag is set in P5 store
  1932   1934   ** the result of comparison (0 or 1 or NULL) into register P2.
................................................................................
  2082   2084     assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
  2083   2085     pIn3->flags = flags3;
  2084   2086   
  2085   2087     if( pOp->p5 & SQLITE_STOREP2 ){
  2086   2088       pOut = &aMem[pOp->p2];
  2087   2089       iCompare = res;
  2088   2090       res2 = res2!=0;  /* For this path res2 must be exactly 0 or 1 */
  2089         -    if( (pOp->p5 & SQLITE_KEEPNULL)!=0 && (pOut->flags & MEM_Null)!=0 ){
         2091  +    if( (pOp->p5 & SQLITE_KEEPNULL)!=0 ){
  2090   2092         /* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1
  2091         -      ** and prevents OP_Ne from overwriting NULL with 0. */
         2093  +      ** and prevents OP_Ne from overwriting NULL with 0.  This flag
         2094  +      ** is only used in contexts where either:
         2095  +      **   (1) op==OP_Eq && (r[P2]==NULL || r[P2]==0)
         2096  +      **   (2) op==OP_Ne && (r[P2]==NULL || r[P2]==1)
         2097  +      ** Therefore it is not necessary to check the content of r[P2] for
         2098  +      ** NULL. */
  2092   2099         assert( pOp->opcode==OP_Ne || pOp->opcode==OP_Eq );
  2093   2100         assert( res2==0 || res2==1 );
         2101  +      testcase( res2==0 && pOp->opcode==OP_Eq );
         2102  +      testcase( res2==1 && pOp->opcode==OP_Eq );
         2103  +      testcase( res2==0 && pOp->opcode==OP_Ne );
         2104  +      testcase( res2==1 && pOp->opcode==OP_Ne );
  2094   2105         if( (pOp->opcode==OP_Eq)==res2 ) break;
  2095   2106       }
  2096   2107       memAboutToChange(p, pOut);
  2097   2108       MemSetTypeFlag(pOut, MEM_Int);
  2098   2109       pOut->u.i = res2;
  2099   2110       REGISTER_TRACE(pOp->p2, pOut);
  2100   2111     }else{