Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge the CAST operator enhancements from trunk. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | threads |
Files: | files | file ages | folders |
SHA1: |
6c8f86e4e08d5d57e21496277613e0f9 |
User & Date: | drh 2014-08-25 22:43:17.516 |
Context
2014-08-25
| ||
23:44 | Remove the SQLITE_CONFIG_WORKER_THREADS configuration parameter. The number of worker threads in the sorter is now determined only by the PRAGMA threads=N setting. (check-in: e3305d4b4e user: drh tags: threads) | |
22:43 | Merge the CAST operator enhancements from trunk. (check-in: 6c8f86e4e0 user: drh tags: threads) | |
22:37 | Add an assert() and five testcase() macros to the OP_Cast opcode implementation to help verify that it is fully tested. (check-in: af364cce9d user: drh tags: trunk) | |
15:13 | Query or change the maximum number of worker threads allowed on each database connection separately using the "PRAGMA threads" command. (check-in: 29c5e8a7c9 user: drh tags: threads) | |
Changes
Changes to src/expr.c.
︙ | |||
2591 2592 2593 2594 2595 2596 2597 | 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 | - - - - - - - - - - - - - - - + + | case TK_AS: { inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); break; } #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ |
︙ |
Changes to src/vdbe.c.
︙ | |||
1764 1765 1766 1767 1768 1769 1770 | 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 | - + - + - - - - + - - + - - - - - - - + - - - - + - - - + - - - + + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - + + - - - - - - - - - - - + - - - - - - - + + - - - - - - - - - - - - + + - + - + | sqlite3VdbeMemRealify(pIn1); } break; } #endif #ifndef SQLITE_OMIT_CAST |
︙ |
Changes to src/vdbeInt.h.
︙ | |||
421 422 423 424 425 426 427 428 429 430 431 432 433 434 | 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 | + | int sqlite3VdbeMemStringify(Mem*, u8, u8); i64 sqlite3VdbeIntValue(Mem*); int sqlite3VdbeMemIntegerify(Mem*); double sqlite3VdbeRealValue(Mem*); void sqlite3VdbeIntegerAffinity(Mem*); int sqlite3VdbeMemRealify(Mem*); int sqlite3VdbeMemNumerify(Mem*); void sqlite3VdbeMemCast(Mem*,u8,u8); int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*); void sqlite3VdbeMemRelease(Mem *p); void sqlite3VdbeMemReleaseExternal(Mem *p); #define VdbeMemDynamic(X) \ (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) #define VdbeMemReleaseExtern(X) \ if( VdbeMemDynamic(X) ) sqlite3VdbeMemReleaseExternal(X); |
︙ |
Changes to src/vdbemem.c.
︙ | |||
405 406 407 408 409 410 411 | 405 406 407 408 409 410 411 412 413 414 415 416 417 418 | - | if( flags & MEM_Int ){ return pMem->u.i; }else if( flags & MEM_Real ){ return doubleToInt64(pMem->r); }else if( flags & (MEM_Str|MEM_Blob) ){ i64 value = 0; assert( pMem->z || pMem->n==0 ); |
︙ | |||
517 518 519 520 521 522 523 524 525 526 527 528 529 530 | 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | sqlite3VdbeIntegerAffinity(pMem); } } assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 ); pMem->flags &= ~(MEM_Str|MEM_Blob); return SQLITE_OK; } /* ** Cast the datatype of the value in pMem according to the affinity ** "aff". Casting is different from applying affinity in that a cast ** is forced. In other words, the value is converted into the desired ** affinity even if that results in loss of data. This routine is ** used (for example) to implement the SQL "cast()" operator. */ void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){ if( pMem->flags & MEM_Null ) return; switch( aff ){ case SQLITE_AFF_NONE: { /* Really a cast to BLOB */ if( (pMem->flags & MEM_Blob)==0 ){ sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); MemSetTypeFlag(pMem, MEM_Blob); }else{ pMem->flags &= ~(MEM_TypeMask&~MEM_Blob); } break; } case SQLITE_AFF_NUMERIC: { sqlite3VdbeMemNumerify(pMem); break; } case SQLITE_AFF_INTEGER: { sqlite3VdbeMemIntegerify(pMem); break; } case SQLITE_AFF_REAL: { sqlite3VdbeMemRealify(pMem); break; } default: { assert( aff==SQLITE_AFF_TEXT ); assert( MEM_Str==(MEM_Blob>>3) ); pMem->flags |= (pMem->flags&MEM_Blob)>>3; sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); pMem->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero); break; } } } /* ** Delete any previous value and set the value stored in *pMem to NULL. */ void sqlite3VdbeMemSetNull(Mem *pMem){ if( pMem->flags & MEM_Frame ){ VdbeFrame *pFrame = pMem->u.pFrame; |
︙ | |||
1011 1012 1013 1014 1015 1016 1017 | 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 | - + + + + + + + + + + + + | const char *zNeg = ""; int rc = SQLITE_OK; if( !pExpr ){ *ppVal = 0; return SQLITE_OK; } |
︙ |
Changes to src/where.c.
︙ | |||
2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 | 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 | + + - - - + | rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); if( rc==SQLITE_OK && bOk ){ tRowcnt iNew; whereKeyStats(pParse, p, pRec, 0, a); iNew = a[0] + ((pLower->eOperator & WO_GT) ? a[1] : 0); if( iNew>iLower ) iLower = iNew; nOut--; pLower = 0; } } /* If possible, improve on the iUpper estimate using ($P:$U). */ if( pUpper ){ int bOk; /* True if value is extracted from pExpr */ Expr *pExpr = pUpper->pExpr->pRight; assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 ); rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); if( rc==SQLITE_OK && bOk ){ tRowcnt iNew; whereKeyStats(pParse, p, pRec, 1, a); iNew = a[0] + ((pUpper->eOperator & WO_LE) ? a[1] : 0); if( iNew<iUpper ) iUpper = iNew; nOut--; pUpper = 0; } } pBuilder->pRec = pRec; if( rc==SQLITE_OK ){ if( iUpper>iLower ){ nNew = sqlite3LogEst(iUpper - iLower); }else{ nNew = 10; assert( 10==sqlite3LogEst(2) ); } if( nNew<nOut ){ nOut = nNew; } |
︙ |
Changes to test/alter4.test.
︙ | |||
141 142 143 144 145 146 147 | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | - + | do_test alter4-2.6 { catchsql { alter table t1 add column d DEFAULT CURRENT_TIME; } } {1 {Cannot add a column with non-constant default}} do_test alter4-2.7 { catchsql { |
︙ |
Changes to test/analyze9.test.
︙ | |||
1083 1084 1085 1086 1087 1088 1089 1090 1091 | 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | 2 "d=0 AND a='z' AND b='n' AND e<100" {/*t5e (e<?)*/} 3 "d=0 AND e<300" {/*t5d (d=?)*/} 4 "d=0 AND e<200" {/*t5e (e<?)*/} } { do_eqp_test 24.$tn "SeLeCt * FROM t5 WHERE $where" $eqp } #------------------------------------------------------------------------- # Test that if stat4 data is available but cannot be used because the # rhs of a range constraint is a complex expression, the default estimates # are used instead. ifcapable stat4&&cte { do_execsql_test 25.1 { CREATE TABLE t6(a, b); WITH ints(i,j) AS ( SELECT 1,1 UNION ALL SELECT i+1,j+1 FROM ints WHERE i<100 ) INSERT INTO t6 SELECT * FROM ints; CREATE INDEX aa ON t6(a); CREATE INDEX bb ON t6(b); ANALYZE; } # Term (b<?) is estimated at 25%. Better than (a<30) but not as # good as (a<20). do_eqp_test 25.2.1 { SELECT * FROM t6 WHERE a<30 AND b<? } { 0 0 0 {SEARCH TABLE t6 USING INDEX bb (b<?)} } do_eqp_test 25.2.2 { SELECT * FROM t6 WHERE a<20 AND b<? } { 0 0 0 {SEARCH TABLE t6 USING INDEX aa (a<?)} } # Term (b BETWEEN ? AND ?) is estimated at 1/64. do_eqp_test 25.3.1 { SELECT * FROM t6 WHERE a BETWEEN 5 AND 10 AND b BETWEEN ? AND ? } { 0 0 0 {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)} } # Term (b BETWEEN ? AND 60) is estimated to return roughly 15 rows - # 60 from (b<=60) multiplied by 0.25 for the b>=? term. Better than # (a<20) but not as good as (a<10). do_eqp_test 25.4.1 { SELECT * FROM t6 WHERE a < 10 AND (b BETWEEN ? AND 60) } { 0 0 0 {SEARCH TABLE t6 USING INDEX aa (a<?)} } do_eqp_test 25.4.2 { SELECT * FROM t6 WHERE a < 20 AND (b BETWEEN ? AND 60) } { 0 0 0 {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)} } } finish_test |
Changes to test/analyzeA.test.
︙ | |||
113 114 115 116 117 118 119 | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | - + | foreach {tn analyze_cmd} { 1 populate_stat4 2 populate_stat3 3 populate_both } { reset_db do_test 1.$tn.1 { |
︙ | |||
157 158 159 160 161 162 163 164 165 166 | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | + + + + + + + + + + + + + + + + + + + + - | do_eqp_test 1.$tn.3.5 { SELECT * FROM t1 WHERE b BETWEEN 0 AND 50 AND c BETWEEN 0 AND 50 } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}} do_eqp_test 1.$tn.3.6 { SELECT * FROM t1 WHERE b BETWEEN 75 AND 125 AND c BETWEEN 75 AND 125 } {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}} do_eqp_test 1.$tn.3.7 { SELECT * FROM t1 WHERE b BETWEEN +0 AND +50 AND c BETWEEN +0 AND +50 } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}} do_eqp_test 1.$tn.3.8 { SELECT * FROM t1 WHERE b BETWEEN cast('0' AS int) AND cast('50.0' AS real) AND c BETWEEN cast('0' AS numeric) AND cast('50.0' AS real) } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}} do_eqp_test 1.$tn.3.9 { SELECT * FROM t1 WHERE b BETWEEN +75 AND +125 AND c BETWEEN +75 AND +125 } {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}} do_eqp_test 1.$tn.3.10 { SELECT * FROM t1 WHERE b BETWEEN cast('75' AS int) AND cast('125.0' AS real) AND c BETWEEN cast('75' AS numeric) AND cast('125.0' AS real) } {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}} } finish_test |