]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
sqlite3MemCompare now takes a CollSeq* argument. (CVS 1419)
authordrh <drh@noemail.net>
Thu, 20 May 2004 13:54:53 +0000 (13:54 +0000)
committerdrh <drh@noemail.net>
Thu, 20 May 2004 13:54:53 +0000 (13:54 +0000)
FossilOrigin-Name: 5c1e47a25244eacc69b688f5f4e62cec9f09665a

manifest
manifest.uuid
src/expr.c
src/vdbe.c
src/vdbe.h
src/vdbeInt.h
src/vdbeaux.c

index 27ab9e542f0885d194e7e5ed089c0af472e8b073..135e363efda063a8c5edd4619ce02a3eda026735 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sproblems\swith\stypes\sand\sthe\srecognition\sof\sBLOB\sas\shaving\sno\saffinity.\s(CVS\s1418)
-D 2004-05-20T12:41:20
+C sqlite3MemCompare\snow\stakes\sa\sCollSeq*\sargument.\s(CVS\s1419)
+D 2004-05-20T13:54:54
 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -32,7 +32,7 @@ F src/copy.c 4d2038602fd0549d80c59bda27d96f13ea9b5e29
 F src/date.c 0eb0a89960bb45c7f7e768748605a7a97b0c8064
 F src/delete.c 2e1dda38345416a1ea1c0a6468589a7472334dac
 F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
-F src/expr.c 34fceec0ae7d9108d6cf98b0685d3d2afa962728
+F src/expr.c 22ee818d11c6dec2a4d1e8117b42c59928995e49
 F src/func.c cfbb7096efb58e2857e3b312a8958a12774b625a
 F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f
 F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb
@@ -64,10 +64,10 @@ F src/update.c 1f6687f8d1085f896a24c0fa13d802223ed55539
 F src/utf.c c27c4f1120f7aaef00cd6942b3d9e3f4ca4fe0e4
 F src/util.c 5cbeb452da09cfc7248de9948c15b14d840723f7
 F src/vacuum.c c134702e023db8778e6be59ac0ea7b02315b5476
-F src/vdbe.c fe412966e48948b680a5bc25796e6e9727174b4b
-F src/vdbe.h 314e9c07db73a42a6ba91ab7539e27652fc88870
-F src/vdbeInt.h 97b95c622ea467d39879ae97d07732ebb4891b76
-F src/vdbeaux.c c48157e910b16010812f67daf981141d3b913e64
+F src/vdbe.c 4aedca4e37bd4762c1ad7f90e0ababf4ad52aa29
+F src/vdbe.h e75fe13aff16cc6e840371f473762615239264e4
+F src/vdbeInt.h 69a7dd040f0656e211d4e20b3cafdcee8461107e
+F src/vdbeaux.c b770802151f30589bd063f434174d230aa043406
 F src/where.c 626b2cbc4290d8be6c04ad7c8395f46d4e21d0d8
 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
 F test/attach.test cb9b884344e6cfa5e165965d5b1adea679a24c83
@@ -195,7 +195,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
 F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 948307f07d6f8cc1cc186167ff7aaa5dfd5d8a2e
-R 59f05a5952887901890856f7cd04108e
+P 8411718f0ac17e9c2376fdf8b5fa0cc5fc88be9b
+R 0120dca1e321b23f5d0817fb2f4d18f3
 U drh
-Z 90bb81f98be65daf25dbb23b209b7296
+Z 85c2c075127be3f9e1f00b69921810df
index ba13805a3723f4ce8900d611c62882994aea4542..e70de3aee0d5927624ef149afcf931c9a6e3586d 100644 (file)
@@ -1 +1 @@
-8411718f0ac17e9c2376fdf8b5fa0cc5fc88be9b
\ No newline at end of file
+5c1e47a25244eacc69b688f5f4e62cec9f09665a
\ No newline at end of file
index 65821bd53509841df288ab37468c4fdbdc7fb86c..1987169e0b9fc279cb6bdc964c07a2112546c62b 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.123 2004/05/19 20:41:03 drh Exp $
+** $Id: expr.c,v 1.124 2004/05/20 13:54:54 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -55,6 +55,11 @@ char sqlite3ExprAffinity(Expr *pExpr){
   return pExpr->affinity;
 }
 
+/*
+** pExpr is the left operand of a comparison operator.  aff2 is the
+** type affinity of the right operand.  This routine returns the
+** type affinity that should be used for the comparison operator.
+*/
 char sqlite3CompareAffinity(Expr *pExpr, char aff2){
   char aff1 = sqlite3ExprAffinity(pExpr);
   if( aff1 && aff2 ){
@@ -79,6 +84,10 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2){
   }
 }
 
+/*
+** pExpr is a comparison operator.  Return the type affinity that should
+** be applied to both operands prior to doing the comparison.
+*/
 static char comparisonAffinity(Expr *pExpr){
   char aff;
   assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
index 03096403d8f9bca969ee1f319841c74a7a86c22b..ee12fc4cceddfb1bfb2cc0673112cfd1fbd053a1 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.307 2004/05/20 02:42:17 drh Exp $
+** $Id: vdbe.c,v 1.308 2004/05/20 13:54:54 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -1484,7 +1484,7 @@ mismatch:
   break;
 }
 
-/* Opcode: Eq P1 P2 *
+/* Opcode: Eq P1 P2 P3
 **
 ** Pop the top two elements from the stack.  If they are equal, then
 ** jump to instruction P2.  Otherwise, continue to the next instruction.
@@ -1508,131 +1508,38 @@ mismatch:
 ** stack if the jump would have been taken, or a 0 if not.  Push a
 ** NULL if either operand was NULL.
 **
+** If P3 is not NULL it is a pointer to a collating sequence (a CollSeq
+** structure) that defines how to compare text.
 */
-/* Opcode: Ne P1 P2 *
+/* Opcode: Ne P1 P2 P3
 **
-** Pop the top two elements from the stack.  If they are not equal, then
-** jump to instruction P2.  Otherwise, continue to the next instruction.
-**
-** The least significant byte of P1 may be either 0x00 or 0x01. If either
-** operand is NULL (and thus if the result is unknown) then take the jump
-** only if the least significant byte of P1 is 0x01.
-**
-** The second least significant byte of P1 must be an affinity character -
-** 'n', 't', 'i' or 'o' - or 0x00. An attempt is made to coerce both values
-** according to the affinity before the comparison is made. If the byte is
-** 0x00, then numeric affinity is used.
-**
-** Once any conversions have taken place, and neither value is NULL, 
-** the values are compared. If both values are blobs, or both are text,
-** then memcmp() is used to determine the results of the comparison. If
-** both values are numeric, then a numeric comparison is used. If the
-** two values are of different types, then they are inequal.
-**
-** If P2 is zero, do not jump.  Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not.  Push a
-** NULL if either operand was NULL.
+** This works just like the Eq opcode except that the jump is taken if
+** the operands from the stack are not equal.  See the Eq opcode for
+** additional information.
 */
-/* Opcode: Lt P1 P2 *
-**
-** Pop the top two elements from the stack.  If second element (the
-** next on stack) is less than the first (the top of stack), then
-** jump to instruction P2.  Otherwise, continue to the next instruction.
-** In other words, jump if NOS<TOS.
+/* Opcode: Lt P1 P2 P3
 **
-** The least significant byte of P1 may be either 0x00 or 0x01. If either
-** operand is NULL (and thus if the result is unknown) then take the jump
-** only if the least significant byte of P1 is 0x01.
-**
-** The second least significant byte of P1 must be an affinity character -
-** 'n', 't', 'i' or 'o' - or 0x00. An attempt is made to coerce both values
-** according to the affinity before the comparison is made. If the byte is
-** 0x00, then numeric affinity is used.
-**
-** Once any conversions have taken place, and neither value is NULL, 
-** the values are compared. If both values are blobs, or both are text,
-** then memcmp() is used to determine the results of the comparison. If
-** both values are numeric, then a numeric comparison is used. If the
-** two values are of different types, then they are inequal.
-**
-** If P2 is zero, do not jump.  Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not.  Push a
-** NULL if either operand was NULL.
+** This works just like the Eq opcode except that the jump is taken if
+** the 2nd element down on the task is less than the top of the stack.
+** See the Eq opcode for additional information.
 */
-/* Opcode: Le P1 P2 *
-**
-** Pop the top two elements from the stack.  If second element (the
-** next on stack) is less than or equal to the first (the top of stack),
-** then jump to instruction P2. In other words, jump if NOS<=TOS.
-**
-** The least significant byte of P1 may be either 0x00 or 0x01. If either
-** operand is NULL (and thus if the result is unknown) then take the jump
-** only if the least significant byte of P1 is 0x01.
+/* Opcode: Le P1 P2 P3
 **
-** The second least significant byte of P1 must be an affinity character -
-** 'n', 't', 'i' or 'o' - or 0x00. An attempt is made to coerce both values
-** according to the affinity before the comparison is made. If the byte is
-** 0x00, then numeric affinity is used.
-**
-** Once any conversions have taken place, and neither value is NULL, 
-** the values are compared. If both values are blobs, or both are text,
-** then memcmp() is used to determine the results of the comparison. If
-** both values are numeric, then a numeric comparison is used. If the
-** two values are of different types, then they are inequal.
-**
-** If P2 is zero, do not jump.  Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not.  Push a
-** NULL if either operand was NULL.
+** This works just like the Eq opcode except that the jump is taken if
+** the 2nd element down on the task is less than or equal to the
+** top of the stack.  See the Eq opcode for additional information.
 */
-/* Opcode: Gt P1 P2 *
-**
-** Pop the top two elements from the stack.  If second element (the
-** next on stack) is greater than the first (the top of stack),
-** then jump to instruction P2. In other words, jump if NOS>TOS.
-**
-** The least significant byte of P1 may be either 0x00 or 0x01. If either
-** operand is NULL (and thus if the result is unknown) then take the jump
-** only if the least significant byte of P1 is 0x01.
-**
-** The second least significant byte of P1 must be an affinity character -
-** 'n', 't', 'i' or 'o' - or 0x00. An attempt is made to coerce both values
-** according to the affinity before the comparison is made. If the byte is
-** 0x00, then numeric affinity is used.
-**
-** Once any conversions have taken place, and neither value is NULL, 
-** the values are compared. If both values are blobs, or both are text,
-** then memcmp() is used to determine the results of the comparison. If
-** both values are numeric, then a numeric comparison is used. If the
-** two values are of different types, then they are inequal.
+/* Opcode: Gt P1 P2 P3
 **
-** If P2 is zero, do not jump.  Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not.  Push a
-** NULL if either operand was NULL.
+** This works just like the Eq opcode except that the jump is taken if
+** the 2nd element down on the task is greater than the top of the stack.
+** See the Eq opcode for additional information.
 */
-/* Opcode: Ge P1 P2 *
-**
-** Pop the top two elements from the stack.  If second element (the next
-** on stack) is greater than or equal to the first (the top of stack),
-** then jump to instruction P2. In other words, jump if NOS>=TOS.
-**
-** The least significant byte of P1 may be either 0x00 or 0x01. If either
-** operand is NULL (and thus if the result is unknown) then take the jump
-** only if the least significant byte of P1 is 0x01.
-**
-** The second least significant byte of P1 must be an affinity character -
-** 'n', 't', 'i' or 'o' - or 0x00. An attempt is made to coerce both values
-** according to the affinity before the comparison is made. If the byte is
-** 0x00, then numeric affinity is used.
-**
-** Once any conversions have taken place, and neither value is NULL, 
-** the values are compared. If both values are blobs, or both are text,
-** then memcmp() is used to determine the results of the comparison. If
-** both values are numeric, then a numeric comparison is used. If the
-** two values are of different types, then they are inequal.
+/* Opcode: Ge P1 P2 P3
 **
-** If P2 is zero, do not jump.  Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not.  Push a
-** NULL if either operand was NULL.
+** This works just like the Eq opcode except that the jump is taken if
+** the 2nd element down on the task is greater than or equal to the
+** top of the stack.  See the Eq opcode for additional information.
 */
 case OP_Eq:
 case OP_Ne:
@@ -1668,7 +1575,8 @@ case OP_Ge: {
   applyAffinity(pNos, affinity);
   applyAffinity(pTos, affinity);
 
-  res = sqlite3MemCompare(pNos, pTos);
+  assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 );
+  res = sqlite3MemCompare(pNos, pTos, (CollSeq*)pOp->p3);
   switch( pOp->opcode ){
     case OP_Eq:    res = res==0;     break;
     case OP_Ne:    res = res!=0;     break;
index 62db796cada32cdc5237b111612d3135e286d06f..b997ce98fb730eb184558452e40506ed84665689 100644 (file)
@@ -15,7 +15,7 @@
 ** or VDBE.  The VDBE implements an abstract machine that runs a
 ** simple program to access and modify the underlying database.
 **
-** $Id: vdbe.h,v 1.77 2004/05/18 23:21:36 drh Exp $
+** $Id: vdbe.h,v 1.78 2004/05/20 13:54:54 drh Exp $
 */
 #ifndef _SQLITE_VDBE_H_
 #define _SQLITE_VDBE_H_
@@ -65,6 +65,7 @@ typedef struct VdbeOpList VdbeOpList;
 #define P3_DYNAMIC  (-1)  /* Pointer to a string obtained from sqliteMalloc() */
 #define P3_STATIC   (-2)  /* Pointer to a static string */
 #define P3_POINTER  (-3)  /* P3 is a pointer to some structure or object */
+#define P3_COLLSEQ  (-4)  /* P3 is a pointer to a CollSeq structure */
 
 /*
 ** The following macro converts a relative address in the p2 field
index 4f5d0f714753531f2d4472530b4a118fb678c2da..3751126aac50b15a7d5eaa8344cd451bb4aea062 100644 (file)
@@ -332,6 +332,6 @@ int sqlite3VdbeSerialGet(const unsigned char *, u64, Mem *);
 int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
 int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int*);
 int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
-int sqlite3MemCompare(Mem *, Mem *);
+int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
 int sqlite3VdbeKeyCompare(void*,int,const void*,int, const void*);
 int sqlite3VdbeRowCompare(void*,int,const void*,int, const void*);
index 19ed03512242a20b4667c8c807720626c4e7ab26..45c104bb3cd6bdfc1773637f41907173b99d00e5 100644 (file)
@@ -1426,15 +1426,28 @@ int sqlite3VdbeSerialGet(const unsigned char *buf, u64 serial_type, Mem *pMem){
 **
 ** Two NULL values are considered equal by this function.
 */
-int sqlite3MemCompare(Mem *pMem1, Mem *pMem2){
+int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
   int rc;
-  int combined_flags = pMem1->flags|pMem2->flags; 
+  int f1, f2;
+  int combined_flags;
+
+  /* Interchange pMem1 and pMem2 if the collating sequence specifies
+  ** DESC order.
+  */
+  if( pColl && pColl->reverseOrder ){
+    const Mem *pTemp = pMem1;
+    pMem1 = pMem2;
+    pMem2 = pTemp;
+  }
+  f1 = pMem1->flags;
+  f2 = pMem2->flags;
+  combined_flags = f1|f2;
  
   /* If one value is NULL, it is less than the other. If both values
   ** are NULL, return 0.
   */
   if( combined_flags&MEM_Null ){
-    return (pMem2->flags&MEM_Null) - (pMem1->flags&MEM_Null);
+    return (f2&MEM_Null) - (f1&MEM_Null);
   }
 
   /* If one value is a number and the other is not, the number is less.
@@ -1442,44 +1455,61 @@ int sqlite3MemCompare(Mem *pMem1, Mem *pMem2){
   ** if both values are integers.
   */
   if( combined_flags&(MEM_Int|MEM_Real) ){
-    i64 diff;
-    if( !(pMem1->flags&(MEM_Int|MEM_Real)) ){
+    if( !(f1&(MEM_Int|MEM_Real)) ){
       return 1;
     }
-    if( !(pMem2->flags&(MEM_Int|MEM_Real)) ){
+    if( !(f2&(MEM_Int|MEM_Real)) ){
       return -1;
     }
-    if( combined_flags&MEM_Real ){
-      if( pMem1->flags&MEM_Int ){
-        pMem1->r = pMem1->i;
+    if( (f1 & f2 & MEM_Int)==0 ){
+      double r1, r2;
+      if( (f1&MEM_Real)==0 ){
+        r1 = pMem1->i;
+      }else{
+        r1 = pMem1->r;
       }
-      if( pMem2->flags&MEM_Int ){
-        pMem2->r = pMem2->i;
+      if( (f2&MEM_Real)==0 ){
+        r2 = pMem2->i;
+      }else{
+        r2 = pMem2->r;
       }
-      if( pMem1->r < pMem2->r ) return -1;
-      if( pMem1->r > pMem2->r ) return 1;
+      if( r1<r2 ) return -1;
+      if( r1>r2 ) return 1;
+      return 0;
+    }else{
+      assert( f1&MEM_Int );
+      assert( f2&MEM_Int );
+      if( pMem1->i < pMem2->i ) return -1;
+      if( pMem1->i > pMem2->i ) return 1;
       return 0;
     }
-    diff = pMem1->i - pMem2->i;
-    return diff<0 ? -1 : diff==0 ? 0 : +1;
   }
 
-  rc = (pMem2->flags&MEM_Null) - (pMem1->flags&MEM_Null);
-  if( rc ){
-    return rc;
+  /* If one value is a string and the other is a blob, the string is less.
+  ** If both are strings, compare using the collating functions.
+  */
+  if( combined_flags&MEM_Str ){
+    if( (f1 & MEM_Str)==0 ){
+      return 1;
+    }
+    if( (f2 & MEM_Str)==0 ){
+      return -1;
+    }
+    if( pColl && pColl->xCmp ){
+      return pColl->xCmp(pColl->pUser, pMem1->n, pMem1->z, pMem2->n, pMem2->z);
+    }else{
+      /* If no collating sequence is defined, fall through into the
+      ** blob case below and use memcmp() for the comparison. */
+    }
   }
-
-  /* Both values must be strings or blobs. If only one is a string, then
-  ** that value is less. Otherwise, compare with memcmp(). If memcmp()
-  ** returns 0 and one value is longer than the other, then that value
-  ** is greater.
+  /* Both values must be blobs.  Compare using memcmp().
   */
   rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
-  if( rc ){
-    return rc;
+  if( rc==0 ){
+    rc = pMem1->n - pMem2->n;
   }
-
-  return (pMem1->n - pMem2->n);
+  return rc;
 }
 
 /*
@@ -1539,7 +1569,7 @@ int sqlite3VdbeKeyCompare(
     offset1 += sqlite3VdbeSerialGet(&aKey1[offset1], serial_type1, &mem1);
     offset2 += sqlite3VdbeSerialGet(&aKey2[offset2], serial_type2, &mem2);
 
-    rc = sqlite3MemCompare(&mem1, &mem2);
+    rc = sqlite3MemCompare(&mem1, &mem2, 0);
     if( mem1.flags&MEM_Dyn ){
       sqliteFree(mem1.z);
     }
@@ -1624,7 +1654,7 @@ int sqlite3VdbeRowCompare(
     offset1 += sqlite3VdbeSerialGet(&aKey1[offset1], serial_type1, &mem1);
     offset2 += sqlite3VdbeSerialGet(&aKey2[offset2], serial_type2, &mem2);
 
-    rc = sqlite3MemCompare(&mem1, &mem2);
+    rc = sqlite3MemCompare(&mem1, &mem2, 0);
     if( mem1.flags&MEM_Dyn ){
       sqliteFree(mem1.z);
     }