Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge all recent changes from trunk. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | apple-osx |
Files: | files | file ages | folders |
SHA3-256: |
c23ef5e231908450da7461233bc3f4a3 |
User & Date: | drh 2017-04-08 18:24:57 |
Context
2017-04-24
| ||
16:14 | Bring in all the latest enhancements from trunk. check-in: 031feebc user: drh tags: apple-osx | |
2017-04-08
| ||
18:24 | Merge all recent changes from trunk. check-in: c23ef5e2 user: drh tags: apple-osx | |
18:18 | Disallow leading zeros on numeric constants in JSON. Fix for ticket [b93be8729a895a528e2] check-in: 204e72f0 user: drh tags: trunk | |
00:25 | Merge the latest trunk changes. check-in: dd16439e user: drh tags: apple-osx | |
Changes
Changes to ext/fts5/fts5Int.h.
442 442 Fts5Index *p, /* Index to write to */ 443 443 int bDelete, /* True if current operation is a delete */ 444 444 i64 iDocid /* Docid to add or remove data from */ 445 445 ); 446 446 447 447 /* 448 448 ** Flush any data stored in the in-memory hash tables to the database. 449 -** If the bCommit flag is true, also close any open blob handles. 449 +** Also close any open blob handles. 450 450 */ 451 -int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit); 451 +int sqlite3Fts5IndexSync(Fts5Index *p); 452 452 453 453 /* 454 454 ** Discard any data stored in the in-memory hash tables. Do not write it 455 455 ** to the database. Additionally, assume that the contents of the %_data 456 456 ** table may have changed on disk. So any in-memory caches of %_data 457 457 ** records must be invalidated. 458 458 */ ................................................................................ 614 614 int sqlite3Fts5StorageStmt(Fts5Storage *p, int eStmt, sqlite3_stmt**, char**); 615 615 void sqlite3Fts5StorageStmtRelease(Fts5Storage *p, int eStmt, sqlite3_stmt*); 616 616 617 617 int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol); 618 618 int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnAvg); 619 619 int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow); 620 620 621 -int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit); 621 +int sqlite3Fts5StorageSync(Fts5Storage *p); 622 622 int sqlite3Fts5StorageRollback(Fts5Storage *p); 623 623 624 624 int sqlite3Fts5StorageConfigValue( 625 625 Fts5Storage *p, const char*, sqlite3_value*, int 626 626 ); 627 627 628 628 int sqlite3Fts5StorageDeleteAll(Fts5Storage *p);
Changes to ext/fts5/fts5_index.c.
624 624 if( p->pReader ){ 625 625 sqlite3_blob *pReader = p->pReader; 626 626 p->pReader = 0; 627 627 sqlite3_blob_close(pReader); 628 628 } 629 629 } 630 630 631 - 632 631 /* 633 632 ** Retrieve a record from the %_data table. 634 633 ** 635 634 ** If an error occurs, NULL is returned and an error left in the 636 635 ** Fts5Index object. 637 636 */ 638 637 static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){ ................................................................................ 5127 5126 p->bDelete = bDelete; 5128 5127 return fts5IndexReturn(p); 5129 5128 } 5130 5129 5131 5130 /* 5132 5131 ** Commit data to disk. 5133 5132 */ 5134 -int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit){ 5133 +int sqlite3Fts5IndexSync(Fts5Index *p){ 5135 5134 assert( p->rc==SQLITE_OK ); 5136 5135 fts5IndexFlush(p); 5137 - if( bCommit ) fts5CloseReader(p); 5136 + fts5CloseReader(p); 5138 5137 return fts5IndexReturn(p); 5139 5138 } 5140 5139 5141 5140 /* 5142 5141 ** Discard any data stored in the in-memory hash tables. Do not write it 5143 5142 ** to the database. Additionally, assume that the contents of the %_data 5144 5143 ** table may have changed on disk. So any in-memory caches of %_data
Changes to ext/fts5/fts5_main.c.
1575 1575 */ 1576 1576 static int fts5SyncMethod(sqlite3_vtab *pVtab){ 1577 1577 int rc; 1578 1578 Fts5Table *pTab = (Fts5Table*)pVtab; 1579 1579 fts5CheckTransactionState(pTab, FTS5_SYNC, 0); 1580 1580 pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg; 1581 1581 fts5TripCursors(pTab); 1582 - rc = sqlite3Fts5StorageSync(pTab->pStorage, 1); 1582 + rc = sqlite3Fts5StorageSync(pTab->pStorage); 1583 1583 pTab->pConfig->pzErrmsg = 0; 1584 1584 return rc; 1585 1585 } 1586 1586 1587 1587 /* 1588 1588 ** Implementation of xBegin() method. 1589 1589 */ ................................................................................ 2386 2386 ** Flush the contents of the pending-terms table to disk. 2387 2387 */ 2388 2388 static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ 2389 2389 Fts5Table *pTab = (Fts5Table*)pVtab; 2390 2390 UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ 2391 2391 fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint); 2392 2392 fts5TripCursors(pTab); 2393 - return sqlite3Fts5StorageSync(pTab->pStorage, 0); 2393 + return sqlite3Fts5StorageSync(pTab->pStorage); 2394 2394 } 2395 2395 2396 2396 /* 2397 2397 ** The xRelease() method. 2398 2398 ** 2399 2399 ** This is a no-op. 2400 2400 */ 2401 2401 static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ 2402 2402 Fts5Table *pTab = (Fts5Table*)pVtab; 2403 2403 UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ 2404 2404 fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint); 2405 2405 fts5TripCursors(pTab); 2406 - return sqlite3Fts5StorageSync(pTab->pStorage, 0); 2406 + return sqlite3Fts5StorageSync(pTab->pStorage); 2407 2407 } 2408 2408 2409 2409 /* 2410 2410 ** The xRollbackTo() method. 2411 2411 ** 2412 2412 ** Discard the contents of the pending terms table. 2413 2413 */
Changes to ext/fts5/fts5_storage.c.
214 214 pConfig->zDb, pConfig->zName, zTail, zName, zTail 215 215 ); 216 216 } 217 217 } 218 218 219 219 int sqlite3Fts5StorageRename(Fts5Storage *pStorage, const char *zName){ 220 220 Fts5Config *pConfig = pStorage->pConfig; 221 - int rc = sqlite3Fts5StorageSync(pStorage, 1); 221 + int rc = sqlite3Fts5StorageSync(pStorage); 222 222 223 223 fts5StorageRenameOne(pConfig, &rc, "data", zName); 224 224 fts5StorageRenameOne(pConfig, &rc, "idx", zName); 225 225 fts5StorageRenameOne(pConfig, &rc, "config", zName); 226 226 if( pConfig->bColumnsize ){ 227 227 fts5StorageRenameOne(pConfig, &rc, "docsize", zName); 228 228 } ................................................................................ 1077 1077 } 1078 1078 return rc; 1079 1079 } 1080 1080 1081 1081 /* 1082 1082 ** Flush any data currently held in-memory to disk. 1083 1083 */ 1084 -int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit){ 1084 +int sqlite3Fts5StorageSync(Fts5Storage *p){ 1085 1085 int rc = SQLITE_OK; 1086 1086 i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db); 1087 1087 if( p->bTotalsValid ){ 1088 1088 rc = fts5StorageSaveTotals(p); 1089 - if( bCommit ) p->bTotalsValid = 0; 1089 + p->bTotalsValid = 0; 1090 1090 } 1091 1091 if( rc==SQLITE_OK ){ 1092 - rc = sqlite3Fts5IndexSync(p->pIndex, bCommit); 1092 + rc = sqlite3Fts5IndexSync(p->pIndex); 1093 1093 } 1094 1094 sqlite3_set_last_insert_rowid(p->pConfig->db, iLastRowid); 1095 1095 return rc; 1096 1096 } 1097 1097 1098 1098 int sqlite3Fts5StorageRollback(Fts5Storage *p){ 1099 1099 p->bTotalsValid = 0;
Changes to ext/fts5/test/fts5aa.test.
556 556 ] 557 557 do_test 20.1 { 558 558 foreach id $::ids { 559 559 execsql { INSERT INTO tmp(rowid, x) VALUES($id, 'x y z') } 560 560 } 561 561 execsql { SELECT rowid FROM tmp WHERE tmp MATCH 'y' } 562 562 } $::ids 563 + 564 +#-------------------------------------------------------------------- 565 +# Test that a DROP TABLE may be executed within a transaction that 566 +# writes to an FTS5 table. 567 +# 568 +do_execsql_test 21.0 { 569 + CREATE TEMP TABLE t8(a, b); 570 + CREATE VIRTUAL TABLE ft USING fts5(x, detail=%DETAIL%); 571 +} 572 + 573 +do_execsql_test 21.1 { 574 + BEGIN; 575 + INSERT INTO ft VALUES('a b c'); 576 + DROP TABLE t8; 577 + COMMIT; 578 +} 563 579 564 580 } 565 581 566 582 567 583 finish_test 568 584 569 585
Changes to ext/misc/json1.c.
723 723 */ 724 724 static int jsonParseValue(JsonParse *pParse, u32 i){ 725 725 char c; 726 726 u32 j; 727 727 int iThis; 728 728 int x; 729 729 JsonNode *pNode; 730 - while( safe_isspace(pParse->zJson[i]) ){ i++; } 731 - if( (c = pParse->zJson[i])=='{' ){ 730 + const char *z = pParse->zJson; 731 + while( safe_isspace(z[i]) ){ i++; } 732 + if( (c = z[i])=='{' ){ 732 733 /* Parse object */ 733 734 iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); 734 735 if( iThis<0 ) return -1; 735 736 for(j=i+1;;j++){ 736 - while( safe_isspace(pParse->zJson[j]) ){ j++; } 737 + while( safe_isspace(z[j]) ){ j++; } 737 738 x = jsonParseValue(pParse, j); 738 739 if( x<0 ){ 739 740 if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1; 740 741 return -1; 741 742 } 742 743 if( pParse->oom ) return -1; 743 744 pNode = &pParse->aNode[pParse->nNode-1]; 744 745 if( pNode->eType!=JSON_STRING ) return -1; 745 746 pNode->jnFlags |= JNODE_LABEL; 746 747 j = x; 747 - while( safe_isspace(pParse->zJson[j]) ){ j++; } 748 - if( pParse->zJson[j]!=':' ) return -1; 748 + while( safe_isspace(z[j]) ){ j++; } 749 + if( z[j]!=':' ) return -1; 749 750 j++; 750 751 x = jsonParseValue(pParse, j); 751 752 if( x<0 ) return -1; 752 753 j = x; 753 - while( safe_isspace(pParse->zJson[j]) ){ j++; } 754 - c = pParse->zJson[j]; 754 + while( safe_isspace(z[j]) ){ j++; } 755 + c = z[j]; 755 756 if( c==',' ) continue; 756 757 if( c!='}' ) return -1; 757 758 break; 758 759 } 759 760 pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1; 760 761 return j+1; 761 762 }else if( c=='[' ){ 762 763 /* Parse array */ 763 764 iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0); 764 765 if( iThis<0 ) return -1; 765 766 for(j=i+1;;j++){ 766 - while( safe_isspace(pParse->zJson[j]) ){ j++; } 767 + while( safe_isspace(z[j]) ){ j++; } 767 768 x = jsonParseValue(pParse, j); 768 769 if( x<0 ){ 769 770 if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1; 770 771 return -1; 771 772 } 772 773 j = x; 773 - while( safe_isspace(pParse->zJson[j]) ){ j++; } 774 - c = pParse->zJson[j]; 774 + while( safe_isspace(z[j]) ){ j++; } 775 + c = z[j]; 775 776 if( c==',' ) continue; 776 777 if( c!=']' ) return -1; 777 778 break; 778 779 } 779 780 pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1; 780 781 return j+1; 781 782 }else if( c=='"' ){ 782 783 /* Parse string */ 783 784 u8 jnFlags = 0; 784 785 j = i+1; 785 786 for(;;){ 786 - c = pParse->zJson[j]; 787 + c = z[j]; 787 788 if( c==0 ) return -1; 788 789 if( c=='\\' ){ 789 - c = pParse->zJson[++j]; 790 + c = z[++j]; 790 791 if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f' 791 792 || c=='n' || c=='r' || c=='t' 792 - || (c=='u' && jsonIs4Hex(pParse->zJson+j+1)) ){ 793 + || (c=='u' && jsonIs4Hex(z+j+1)) ){ 793 794 jnFlags = JNODE_ESCAPE; 794 795 }else{ 795 796 return -1; 796 797 } 797 798 }else if( c=='"' ){ 798 799 break; 799 800 } 800 801 j++; 801 802 } 802 - jsonParseAddNode(pParse, JSON_STRING, j+1-i, &pParse->zJson[i]); 803 + jsonParseAddNode(pParse, JSON_STRING, j+1-i, &z[i]); 803 804 if( !pParse->oom ) pParse->aNode[pParse->nNode-1].jnFlags = jnFlags; 804 805 return j+1; 805 806 }else if( c=='n' 806 - && strncmp(pParse->zJson+i,"null",4)==0 807 - && !safe_isalnum(pParse->zJson[i+4]) ){ 807 + && strncmp(z+i,"null",4)==0 808 + && !safe_isalnum(z[i+4]) ){ 808 809 jsonParseAddNode(pParse, JSON_NULL, 0, 0); 809 810 return i+4; 810 811 }else if( c=='t' 811 - && strncmp(pParse->zJson+i,"true",4)==0 812 - && !safe_isalnum(pParse->zJson[i+4]) ){ 812 + && strncmp(z+i,"true",4)==0 813 + && !safe_isalnum(z[i+4]) ){ 813 814 jsonParseAddNode(pParse, JSON_TRUE, 0, 0); 814 815 return i+4; 815 816 }else if( c=='f' 816 - && strncmp(pParse->zJson+i,"false",5)==0 817 - && !safe_isalnum(pParse->zJson[i+5]) ){ 817 + && strncmp(z+i,"false",5)==0 818 + && !safe_isalnum(z[i+5]) ){ 818 819 jsonParseAddNode(pParse, JSON_FALSE, 0, 0); 819 820 return i+5; 820 821 }else if( c=='-' || (c>='0' && c<='9') ){ 821 822 /* Parse number */ 822 823 u8 seenDP = 0; 823 824 u8 seenE = 0; 825 + assert( '-' < '0' ); 826 + if( c<='0' ){ 827 + j = c=='-' ? i+1 : i; 828 + if( z[j]=='0' && z[j+1]>='0' && z[j+1]<='9' ) return -1; 829 + } 824 830 j = i+1; 825 831 for(;; j++){ 826 - c = pParse->zJson[j]; 832 + c = z[j]; 827 833 if( c>='0' && c<='9' ) continue; 828 834 if( c=='.' ){ 829 - if( pParse->zJson[j-1]=='-' ) return -1; 835 + if( z[j-1]=='-' ) return -1; 830 836 if( seenDP ) return -1; 831 837 seenDP = 1; 832 838 continue; 833 839 } 834 840 if( c=='e' || c=='E' ){ 835 - if( pParse->zJson[j-1]<'0' ) return -1; 841 + if( z[j-1]<'0' ) return -1; 836 842 if( seenE ) return -1; 837 843 seenDP = seenE = 1; 838 - c = pParse->zJson[j+1]; 844 + c = z[j+1]; 839 845 if( c=='+' || c=='-' ){ 840 846 j++; 841 - c = pParse->zJson[j+1]; 847 + c = z[j+1]; 842 848 } 843 849 if( c<'0' || c>'9' ) return -1; 844 850 continue; 845 851 } 846 852 break; 847 853 } 848 - if( pParse->zJson[j-1]<'0' ) return -1; 854 + if( z[j-1]<'0' ) return -1; 849 855 jsonParseAddNode(pParse, seenDP ? JSON_REAL : JSON_INT, 850 - j - i, &pParse->zJson[i]); 856 + j - i, &z[i]); 851 857 return j; 852 858 }else if( c=='}' ){ 853 859 return -2; /* End of {...} */ 854 860 }else if( c==']' ){ 855 861 return -3; /* End of [...] */ 856 862 }else if( c==0 ){ 857 863 return 0; /* End of file */
Changes to ext/rtree/rtree.c.
3195 3195 "ALTER TABLE %Q.'%q_parent' RENAME TO \"%w_parent\";" 3196 3196 "ALTER TABLE %Q.'%q_rowid' RENAME TO \"%w_rowid\";" 3197 3197 , pRtree->zDb, pRtree->zName, zNewName 3198 3198 , pRtree->zDb, pRtree->zName, zNewName 3199 3199 , pRtree->zDb, pRtree->zName, zNewName 3200 3200 ); 3201 3201 if( zSql ){ 3202 + nodeBlobReset(pRtree); 3202 3203 rc = sqlite3_exec(pRtree->db, zSql, 0, 0, 0); 3203 3204 sqlite3_free(zSql); 3204 3205 } 3205 3206 return rc; 3206 3207 } 3207 3208 3209 +/* 3210 +** The xSavepoint method. 3211 +** 3212 +** This module does not need to do anything to support savepoints. However, 3213 +** it uses this hook to close any open blob handle. This is done because a 3214 +** DROP TABLE command - which fortunately always opens a savepoint - cannot 3215 +** succeed if there are any open blob handles. i.e. if the blob handle were 3216 +** not closed here, the following would fail: 3217 +** 3218 +** BEGIN; 3219 +** INSERT INTO rtree... 3220 +** DROP TABLE <tablename>; -- Would fail with SQLITE_LOCKED 3221 +** COMMIT; 3222 +*/ 3223 +static int rtreeSavepoint(sqlite3_vtab *pVtab, int iSavepoint){ 3224 + Rtree *pRtree = (Rtree *)pVtab; 3225 + int iwt = pRtree->inWrTrans; 3226 + pRtree->inWrTrans = 0; 3227 + nodeBlobReset(pRtree); 3228 + pRtree->inWrTrans = iwt; 3229 + return SQLITE_OK; 3230 +} 3208 3231 3209 3232 /* 3210 3233 ** This function populates the pRtree->nRowEst variable with an estimate 3211 3234 ** of the number of rows in the virtual table. If possible, this is based 3212 3235 ** on sqlite_stat1 data. Otherwise, use RTREE_DEFAULT_ROWEST. 3213 3236 */ 3214 3237 static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){ ................................................................................ 3247 3270 sqlite3_free(zSql); 3248 3271 } 3249 3272 3250 3273 return rc; 3251 3274 } 3252 3275 3253 3276 static sqlite3_module rtreeModule = { 3254 - 0, /* iVersion */ 3277 + 2, /* iVersion */ 3255 3278 rtreeCreate, /* xCreate - create a table */ 3256 3279 rtreeConnect, /* xConnect - connect to an existing table */ 3257 3280 rtreeBestIndex, /* xBestIndex - Determine search strategy */ 3258 3281 rtreeDisconnect, /* xDisconnect - Disconnect from a table */ 3259 3282 rtreeDestroy, /* xDestroy - Drop a table */ 3260 3283 rtreeOpen, /* xOpen - open a cursor */ 3261 3284 rtreeClose, /* xClose - close a cursor */ ................................................................................ 3267 3290 rtreeUpdate, /* xUpdate - write data */ 3268 3291 rtreeBeginTransaction, /* xBegin - begin transaction */ 3269 3292 rtreeEndTransaction, /* xSync - sync transaction */ 3270 3293 rtreeEndTransaction, /* xCommit - commit transaction */ 3271 3294 rtreeEndTransaction, /* xRollback - rollback transaction */ 3272 3295 0, /* xFindFunction - function overloading */ 3273 3296 rtreeRename, /* xRename - rename the table */ 3274 - 0, /* xSavepoint */ 3297 + rtreeSavepoint, /* xSavepoint */ 3275 3298 0, /* xRelease */ 3276 3299 0, /* xRollbackTo */ 3277 3300 }; 3278 3301 3279 3302 static int rtreeSqlInit( 3280 3303 Rtree *pRtree, 3281 3304 sqlite3 *db,
Changes to ext/rtree/rtree1.test.
35 35 # rtree-12.*: Test that on-conflict clauses are supported. 36 36 # rtree-13.*: Test that bug [d2889096e7bdeac6d] has been fixed. 37 37 # rtree-14.*: Test if a non-integer is inserted into the PK column of an 38 38 # r-tree table, it is converted to an integer before being 39 39 # inserted. Also that if a non-numeric is inserted into one 40 40 # of the min/max dimension columns, it is converted to the 41 41 # required type before being inserted. 42 +# rtree-15.*: Check that DROP TABLE works within a transaction that 43 +# writes to an r-tree table. 42 44 # 43 45 44 46 ifcapable !rtree { 45 47 finish_test 46 48 return 47 49 } 48 50 ................................................................................ 587 589 do_execsql_test 14.5 { 588 590 SELECT * FROM t10; 589 591 } { 590 592 1 0 0 591 593 2 52 81 592 594 3 42 49 593 595 } 596 + 597 +#------------------------------------------------------------------------- 598 +# 599 +do_execsql_test 15.0 { 600 + CREATE VIRTUAL TABLE rt USING rtree(id, x1,x2, y1,y2); 601 + CREATE TEMP TABLE t13(a, b, c); 602 +} 603 +do_execsql_test 15.1 { 604 + BEGIN; 605 + INSERT INTO rt VALUES(1,2,3,4,5); 606 +} 607 +breakpoint 608 +do_execsql_test 15.2 { 609 + DROP TABLE t13; 610 + COMMIT; 611 +} 594 612 595 613 finish_test
Changes to src/shell.c.
1508 1508 }while( strstr(z,zBuf)!=0 ); 1509 1509 return zBuf; 1510 1510 } 1511 1511 1512 1512 /* 1513 1513 ** Output the given string as a quoted string using SQL quoting conventions. 1514 1514 ** 1515 -** The "\n" and "\r" characters are converted to char(10) and char(13) 1516 -** to prevent them from being transformed by end-of-line translators. 1515 +** See also: output_quoted_escaped_string() 1517 1516 */ 1518 1517 static void output_quoted_string(FILE *out, const char *z){ 1519 1518 int i; 1519 + char c; 1520 + setBinaryMode(out, 1); 1521 + for(i=0; (c = z[i])!=0 && c!='\''; i++){} 1522 + if( c==0 ){ 1523 + utf8_printf(out,"'%s'",z); 1524 + }else{ 1525 + raw_printf(out, "'"); 1526 + while( *z ){ 1527 + for(i=0; (c = z[i])!=0 && c!='\''; i++){} 1528 + if( c=='\'' ) i++; 1529 + if( i ){ 1530 + utf8_printf(out, "%.*s", i, z); 1531 + z += i; 1532 + } 1533 + if( c=='\'' ){ 1534 + raw_printf(out, "'"); 1535 + continue; 1536 + } 1537 + if( c==0 ){ 1538 + break; 1539 + } 1540 + z++; 1541 + } 1542 + raw_printf(out, "'"); 1543 + } 1544 + setTextMode(out, 1); 1545 +} 1546 + 1547 +/* 1548 +** Output the given string as a quoted string using SQL quoting conventions. 1549 +** Additionallly , escape the "\n" and "\r" characters so that they do not 1550 +** get corrupted by end-of-line translation facilities in some operating 1551 +** systems. 1552 +** 1553 +** This is like output_quoted_string() but with the addition of the \r\n 1554 +** escape mechanism. 1555 +*/ 1556 +static void output_quoted_escaped_string(FILE *out, const char *z){ 1557 + int i; 1520 1558 char c; 1521 1559 setBinaryMode(out, 1); 1522 1560 for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){} 1523 1561 if( c==0 ){ 1524 1562 utf8_printf(out,"'%s'",z); 1525 1563 }else{ 1526 1564 const char *zNL = 0; ................................................................................ 2027 2065 output_csv(p, azArg[i], i<nArg-1); 2028 2066 } 2029 2067 utf8_printf(p->out, "%s", p->rowSeparator); 2030 2068 } 2031 2069 setTextMode(p->out, 1); 2032 2070 break; 2033 2071 } 2034 - case MODE_Quote: 2035 2072 case MODE_Insert: { 2036 2073 if( azArg==0 ) break; 2037 - if( p->cMode==MODE_Insert ){ 2038 - utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); 2039 - if( p->showHeader ){ 2040 - raw_printf(p->out,"("); 2041 - for(i=0; i<nArg; i++){ 2042 - char *zSep = i>0 ? ",": ""; 2043 - utf8_printf(p->out, "%s%s", zSep, azCol[i]); 2044 - } 2045 - raw_printf(p->out,")"); 2046 - } 2047 - raw_printf(p->out," VALUES("); 2048 - }else if( p->cnt==0 && p->showHeader ){ 2074 + utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); 2075 + if( p->showHeader ){ 2076 + raw_printf(p->out,"("); 2077 + for(i=0; i<nArg; i++){ 2078 + if( i>0 ) raw_printf(p->out, ","); 2079 + if( quoteChar(azCol[i]) ){ 2080 + char *z = sqlite3_mprintf("\"%w\"", azCol[i]); 2081 + utf8_printf(p->out, "%s", z); 2082 + sqlite3_free(z); 2083 + }else{ 2084 + raw_printf(p->out, "%s", azCol[i]); 2085 + } 2086 + } 2087 + raw_printf(p->out,")"); 2088 + } 2089 + p->cnt++; 2090 + for(i=0; i<nArg; i++){ 2091 + raw_printf(p->out, i>0 ? "," : " VALUES("); 2092 + if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ 2093 + utf8_printf(p->out,"NULL"); 2094 + }else if( aiType && aiType[i]==SQLITE_TEXT ){ 2095 + output_quoted_escaped_string(p->out, azArg[i]); 2096 + }else if( aiType && aiType[i]==SQLITE_INTEGER ){ 2097 + utf8_printf(p->out,"%s", azArg[i]); 2098 + }else if( aiType && aiType[i]==SQLITE_FLOAT ){ 2099 + char z[50]; 2100 + double r = sqlite3_column_double(p->pStmt, i); 2101 + sqlite3_snprintf(50,z,"%!.20g", r); 2102 + raw_printf(p->out, "%s", z); 2103 + }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ 2104 + const void *pBlob = sqlite3_column_blob(p->pStmt, i); 2105 + int nBlob = sqlite3_column_bytes(p->pStmt, i); 2106 + output_hex_blob(p->out, pBlob, nBlob); 2107 + }else if( isNumber(azArg[i], 0) ){ 2108 + utf8_printf(p->out,"%s", azArg[i]); 2109 + }else{ 2110 + output_quoted_escaped_string(p->out, azArg[i]); 2111 + } 2112 + } 2113 + raw_printf(p->out,");\n"); 2114 + break; 2115 + } 2116 + case MODE_Quote: { 2117 + if( azArg==0 ) break; 2118 + if( p->cnt==0 && p->showHeader ){ 2049 2119 for(i=0; i<nArg; i++){ 2050 2120 if( i>0 ) raw_printf(p->out, ","); 2051 2121 output_quoted_string(p->out, azCol[i]); 2052 2122 } 2053 2123 raw_printf(p->out,"\n"); 2054 2124 } 2055 2125 p->cnt++; 2056 2126 for(i=0; i<nArg; i++){ 2057 - char *zSep = i>0 ? ",": ""; 2127 + if( i>0 ) raw_printf(p->out, ","); 2058 2128 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ 2059 - utf8_printf(p->out,"%sNULL",zSep); 2129 + utf8_printf(p->out,"NULL"); 2060 2130 }else if( aiType && aiType[i]==SQLITE_TEXT ){ 2061 - if( zSep[0] ) utf8_printf(p->out,"%s",zSep); 2062 2131 output_quoted_string(p->out, azArg[i]); 2063 2132 }else if( aiType && aiType[i]==SQLITE_INTEGER ){ 2064 - utf8_printf(p->out,"%s%s",zSep, azArg[i]); 2133 + utf8_printf(p->out,"%s", azArg[i]); 2065 2134 }else if( aiType && aiType[i]==SQLITE_FLOAT ){ 2066 2135 char z[50]; 2067 2136 double r = sqlite3_column_double(p->pStmt, i); 2068 2137 sqlite3_snprintf(50,z,"%!.20g", r); 2069 - raw_printf(p->out, "%s%s", zSep, z); 2138 + raw_printf(p->out, "%s", z); 2070 2139 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ 2071 2140 const void *pBlob = sqlite3_column_blob(p->pStmt, i); 2072 2141 int nBlob = sqlite3_column_bytes(p->pStmt, i); 2073 - if( zSep[0] ) utf8_printf(p->out,"%s",zSep); 2074 2142 output_hex_blob(p->out, pBlob, nBlob); 2075 2143 }else if( isNumber(azArg[i], 0) ){ 2076 - utf8_printf(p->out,"%s%s",zSep, azArg[i]); 2144 + utf8_printf(p->out,"%s", azArg[i]); 2077 2145 }else{ 2078 - if( zSep[0] ) utf8_printf(p->out,"%s",zSep); 2079 2146 output_quoted_string(p->out, azArg[i]); 2080 2147 } 2081 2148 } 2082 - raw_printf(p->out,p->cMode==MODE_Quote?"\n":");\n"); 2149 + raw_printf(p->out,"\n"); 2083 2150 break; 2084 2151 } 2085 2152 case MODE_Ascii: { 2086 2153 if( p->cnt++==0 && p->showHeader ){ 2087 2154 for(i=0; i<nArg; i++){ 2088 2155 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator); 2089 2156 utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : ""); ................................................................................ 4713 4780 if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){ 4714 4781 rc = shell_dbinfo_command(p, nArg, azArg); 4715 4782 }else 4716 4783 4717 4784 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ 4718 4785 const char *zLike = 0; 4719 4786 int i; 4787 + int savedShowHeader = p->showHeader; 4720 4788 ShellClearFlag(p, SHFLG_PreserveRowid); 4721 4789 for(i=1; i<nArg; i++){ 4722 4790 if( azArg[i][0]=='-' ){ 4723 4791 const char *z = azArg[i]+1; 4724 4792 if( z[0]=='-' ) z++; 4725 4793 if( strcmp(z,"preserve-rowids")==0 ){ 4726 4794 #ifdef SQLITE_OMIT_VIRTUALTABLE ................................................................................ 4748 4816 open_db(p, 0); 4749 4817 /* When playing back a "dump", the content might appear in an order 4750 4818 ** which causes immediate foreign key constraints to be violated. 4751 4819 ** So disable foreign-key constraint enforcement to prevent problems. */ 4752 4820 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n"); 4753 4821 raw_printf(p->out, "BEGIN TRANSACTION;\n"); 4754 4822 p->writableSchema = 0; 4823 + p->showHeader = 0; 4755 4824 /* Set writable_schema=ON since doing so forces SQLite to initialize 4756 4825 ** as much of the schema as it can even if the sqlite_master table is 4757 4826 ** corrupt. */ 4758 4827 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); 4759 4828 p->nErr = 0; 4760 4829 if( zLike==0 ){ 4761 4830 run_schema_dump_query(p, ................................................................................ 4789 4858 if( p->writableSchema ){ 4790 4859 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n"); 4791 4860 p->writableSchema = 0; 4792 4861 } 4793 4862 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); 4794 4863 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); 4795 4864 raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n"); 4865 + p->showHeader = savedShowHeader; 4796 4866 }else 4797 4867 4798 4868 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){ 4799 4869 if( nArg==2 ){ 4800 4870 setOrClearFlag(p, SHFLG_Echo, azArg[1]); 4801 4871 }else{ 4802 4872 raw_printf(stderr, "Usage: .echo on|off\n");
Changes to src/vdbe.c.
5383 5383 ** P3==1 then the table to be clear is in the auxiliary database file 5384 5384 ** that is used to store tables create using CREATE TEMPORARY TABLE. 5385 5385 ** 5386 5386 ** If AUTOVACUUM is enabled then it is possible that another root page 5387 5387 ** might be moved into the newly deleted root page in order to keep all 5388 5388 ** root pages contiguous at the beginning of the database. The former 5389 5389 ** value of the root page that moved - its value before the move occurred - 5390 -** is stored in register P2. If no page 5391 -** movement was required (because the table being dropped was already 5392 -** the last one in the database) then a zero is stored in register P2. 5393 -** If AUTOVACUUM is disabled then a zero is stored in register P2. 5390 +** is stored in register P2. If no page movement was required (because the 5391 +** table being dropped was already the last one in the database) then a 5392 +** zero is stored in register P2. If AUTOVACUUM is disabled then a zero 5393 +** is stored in register P2. 5394 +** 5395 +** This opcode throws an error if there are any active reader VMs when 5396 +** it is invoked. This is done to avoid the difficulty associated with 5397 +** updating existing cursors when a root page is moved in an AUTOVACUUM 5398 +** database. This error is thrown even if the database is not an AUTOVACUUM 5399 +** db in order to avoid introducing an incompatibility between autovacuum 5400 +** and non-autovacuum modes. 5394 5401 ** 5395 5402 ** See also: Clear 5396 5403 */ 5397 5404 case OP_Destroy: { /* out2 */ 5398 5405 int iMoved; 5399 5406 int iDb; 5400 5407
Changes to test/json102.test.
293 293 # 294 294 for {set i 0} {$i<100} {incr i} { 295 295 set str abcdef[string repeat \" [expr {$i+50}]]uvwxyz 296 296 do_test json102-[format %d [expr {$i+1300}]] { 297 297 db eval {SELECT json_extract(json_array($::str),'$[0]')==$::str} 298 298 } {1} 299 299 } 300 + 301 +#------------------------------------------------------------------------- 302 +# 2017-04-08 ticket b93be8729a895a528e2849fca99f7 303 +# JSON extension accepts invalid numeric values 304 +# 305 +# JSON does not allow leading zeros. But the JSON extension was 306 +# allowing them. The following tests verify that the problem is now 307 +# fixed. 308 +# 309 +do_execsql_test json102-1401 { SELECT json_valid('{"x":01}') } 0 310 +do_execsql_test json102-1402 { SELECT json_valid('{"x":-01}') } 0 311 +do_execsql_test json102-1403 { SELECT json_valid('{"x":0}') } 1 312 +do_execsql_test json102-1404 { SELECT json_valid('{"x":-0}') } 1 313 +do_execsql_test json102-1405 { SELECT json_valid('{"x":0.1}') } 1 314 +do_execsql_test json102-1406 { SELECT json_valid('{"x":-0.1}') } 1 315 +do_execsql_test json102-1407 { SELECT json_valid('{"x":0.0000}') } 1 316 +do_execsql_test json102-1408 { SELECT json_valid('{"x":-0.0000}') } 1 317 +do_execsql_test json102-1409 { SELECT json_valid('{"x":01.5}') } 0 318 +do_execsql_test json102-1410 { SELECT json_valid('{"x":-01.5}') } 0 319 +do_execsql_test json102-1411 { SELECT json_valid('{"x":00}') } 0 320 +do_execsql_test json102-1412 { SELECT json_valid('{"x":-00}') } 0 300 321 301 322 finish_test