Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | sqlite3MemCompare now takes a CollSeq* argument. (CVS 1419) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
5c1e47a25244eacc69b688f5f4e62cec |
User & Date: | drh 2004-05-20 13:54:54.000 |
Context
2004-05-20
| ||
22:16 | Add internal support for collating sequences. This breaks 244 tests. (CVS 1420) (check-in: a6cb09d7af user: drh tags: trunk) | |
13:54 | sqlite3MemCompare now takes a CollSeq* argument. (CVS 1419) (check-in: 5c1e47a252 user: drh tags: trunk) | |
12:41 | Fix problems with types and the recognition of BLOB as having no affinity. (CVS 1418) (check-in: 8411718f0a user: drh tags: trunk) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.124 2004/05/20 13:54:54 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> char const *sqlite3AffinityString(char affinity){ switch( affinity ){ case SQLITE_AFF_INTEGER: return "i"; |
︙ | ︙ | |||
51 52 53 54 55 56 57 58 59 60 61 62 63 64 | } if( pExpr->op==TK_SELECT ){ return sqlite3ExprAffinity(pExpr->pSelect->pEList->a[0].pExpr); } return pExpr->affinity; } char sqlite3CompareAffinity(Expr *pExpr, char aff2){ char aff1 = sqlite3ExprAffinity(pExpr); if( aff1 && aff2 ){ /* Both sides of the comparison are columns. If one has numeric or ** integer affinity, use that. Otherwise use no affinity. */ if( aff1==SQLITE_AFF_INTEGER || aff2==SQLITE_AFF_INTEGER ){ | > > > > > | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | } if( pExpr->op==TK_SELECT ){ return sqlite3ExprAffinity(pExpr->pSelect->pEList->a[0].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 ){ /* Both sides of the comparison are columns. If one has numeric or ** integer affinity, use that. Otherwise use no affinity. */ if( aff1==SQLITE_AFF_INTEGER || aff2==SQLITE_AFF_INTEGER ){ |
︙ | ︙ | |||
75 76 77 78 79 80 81 82 83 84 85 86 87 88 | return SQLITE_AFF_NUMERIC; }else{ /* One side is a column, the other is not. Use the columns affinity. */ return (aff1 + aff2); } } static char comparisonAffinity(Expr *pExpr){ char aff; assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT || pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE || pExpr->op==TK_NE ); assert( pExpr->pLeft ); aff = sqlite3ExprAffinity(pExpr->pLeft); | > > > > | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | return SQLITE_AFF_NUMERIC; }else{ /* One side is a column, the other is not. Use the columns affinity. */ return (aff1 + 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 || pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE || pExpr->op==TK_NE ); assert( pExpr->pLeft ); aff = sqlite3ExprAffinity(pExpr->pLeft); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** 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.308 2004/05/20 13:54:54 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
1480 1481 1482 1483 1484 1485 1486 | }else{ if( pOp->p1 ) popStack(&pTos, 1); pc = pOp->p2 - 1; } break; } | | | 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 | }else{ if( pOp->p1 ) popStack(&pTos, 1); pc = pOp->p2 - 1; } break; } /* 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. ** ** 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. |
︙ | ︙ | |||
1504 1505 1506 1507 1508 1509 1510 1511 | ** 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. ** */ | > > | > | < | < < < < < < < < < < < < < < < < < < | < > | < < < < < < < < < < < < < < < < < < < < < > | < < < < < < < < < < < < < < > | < < < < < < < > | < > | < < < < < < < < < < < < < < < < < < < < > | < > | < < < < | < < < < < < < < < < < < < < < | 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 | ** 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. ** ** 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 P3 ** ** 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 P3 ** ** 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 P3 ** ** 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 P3 ** ** 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 P3 ** ** 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: case OP_Lt: case OP_Le: case OP_Gt: case OP_Ge: { |
︙ | ︙ | |||
1664 1665 1666 1667 1668 1669 1670 | } affinity = (pOp->p1>>8)&0xFF; if( affinity=='\0' ) affinity = 'n'; applyAffinity(pNos, affinity); applyAffinity(pTos, affinity); | > | | 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 | } affinity = (pOp->p1>>8)&0xFF; if( affinity=='\0' ) affinity = 'n'; applyAffinity(pNos, affinity); applyAffinity(pTos, affinity); 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; case OP_Lt: res = res<0; break; case OP_Le: res = res<=0; break; case OP_Gt: res = res>0; break; default: res = res>=0; break; |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** 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.78 2004/05/20 13:54:54 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
61 62 63 64 65 66 67 68 69 70 71 72 73 74 | /* ** Allowed values of VdbeOp.p3type */ #define P3_NOTUSED 0 /* The P3 parameter is not used */ #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 */ /* ** The following macro converts a relative address in the p2 field ** of a VdbeOp structure into a negative number so that ** sqlite3VdbeAddOpList() knows that the address is relative. Calling ** the macro again restores the address. */ | > | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | /* ** Allowed values of VdbeOp.p3type */ #define P3_NOTUSED 0 /* The P3 parameter is not used */ #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 ** of a VdbeOp structure into a negative number so that ** sqlite3VdbeAddOpList() knows that the address is relative. Calling ** the macro again restores the address. */ |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
328 329 330 331 332 333 334 | u64 sqlite3VdbeSerialType(const Mem *); int sqlite3VdbeSerialPut(unsigned char *, const Mem *); 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 *); | | | 328 329 330 331 332 333 334 335 336 337 | u64 sqlite3VdbeSerialType(const Mem *); int sqlite3VdbeSerialPut(unsigned char *, const Mem *); 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(const Mem*, const Mem*, const CollSeq*); int sqlite3VdbeKeyCompare(void*,int,const void*,int, const void*); int sqlite3VdbeRowCompare(void*,int,const void*,int, const void*); |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
1422 1423 1424 1425 1426 1427 1428 | ** negative, zero or positive if pMem1 is less than, equal to, or greater ** than pMem2. Sorting order is NULL's first, followed by numbers (integers ** and reals) sorted numerically, followed by text ordered by memcmp() and ** finally blob's ordered by memcmp(). ** ** Two NULL values are considered equal by this function. */ | | > | > > > > > > > > > > > > | < | | > > | | > | > | > | | | > > > > > > < < > > > | | | | > > | < > > > > | > > | < > | | < | | 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 | ** negative, zero or positive if pMem1 is less than, equal to, or greater ** than pMem2. Sorting order is NULL's first, followed by numbers (integers ** and reals) sorted numerically, followed by text ordered by memcmp() and ** finally blob's ordered by memcmp(). ** ** Two NULL values are considered equal by this function. */ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ int rc; 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 (f2&MEM_Null) - (f1&MEM_Null); } /* If one value is a number and the other is not, the number is less. ** If both are numbers, compare as reals if one is a real, or as integers ** if both values are integers. */ if( combined_flags&(MEM_Int|MEM_Real) ){ if( !(f1&(MEM_Int|MEM_Real)) ){ return 1; } if( !(f2&(MEM_Int|MEM_Real)) ){ return -1; } if( (f1 & f2 & MEM_Int)==0 ){ double r1, r2; if( (f1&MEM_Real)==0 ){ r1 = pMem1->i; }else{ r1 = pMem1->r; } if( (f2&MEM_Real)==0 ){ r2 = pMem2->i; }else{ r2 = pMem2->r; } 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; } } /* 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 blobs. Compare using memcmp(). */ rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n); if( rc==0 ){ rc = pMem1->n - pMem2->n; } return rc; } /* ** The following is the comparison function for (non-integer) ** keys in the btrees. This function returns negative, zero, or ** positive if the first key is less than, equal to, or greater than ** the second. |
︙ | ︙ | |||
1535 1536 1537 1538 1539 1540 1541 | ** data to go with the serial type just read. This assert may fail if ** the file is corrupted. Then read the value from each key into mem1 ** and mem2 respectively. */ offset1 += sqlite3VdbeSerialGet(&aKey1[offset1], serial_type1, &mem1); offset2 += sqlite3VdbeSerialGet(&aKey2[offset2], serial_type2, &mem2); | | | 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 | ** data to go with the serial type just read. This assert may fail if ** the file is corrupted. Then read the value from each key into mem1 ** and mem2 respectively. */ offset1 += sqlite3VdbeSerialGet(&aKey1[offset1], serial_type1, &mem1); offset2 += sqlite3VdbeSerialGet(&aKey2[offset2], serial_type2, &mem2); rc = sqlite3MemCompare(&mem1, &mem2, 0); if( mem1.flags&MEM_Dyn ){ sqliteFree(mem1.z); } if( mem2.flags&MEM_Dyn ){ sqliteFree(mem2.z); } if( rc!=0 ){ |
︙ | ︙ | |||
1620 1621 1622 1623 1624 1625 1626 | ** data to go with the serial type just read. This assert may fail if ** the file is corrupted. Then read the value from each key into mem1 ** and mem2 respectively. */ offset1 += sqlite3VdbeSerialGet(&aKey1[offset1], serial_type1, &mem1); offset2 += sqlite3VdbeSerialGet(&aKey2[offset2], serial_type2, &mem2); | | | 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 | ** data to go with the serial type just read. This assert may fail if ** the file is corrupted. Then read the value from each key into mem1 ** and mem2 respectively. */ offset1 += sqlite3VdbeSerialGet(&aKey1[offset1], serial_type1, &mem1); offset2 += sqlite3VdbeSerialGet(&aKey2[offset2], serial_type2, &mem2); rc = sqlite3MemCompare(&mem1, &mem2, 0); if( mem1.flags&MEM_Dyn ){ sqliteFree(mem1.z); } if( mem2.flags&MEM_Dyn ){ sqliteFree(mem2.z); } if( rc!=0 ){ |
︙ | ︙ |