Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Switch back to using a single database connection in sqlite3ota.c. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | ota-update |
Files: | files | file ages | folders |
SHA1: |
3c2f4a078132992e33cc675173c84f83 |
User & Date: | dan 2014-09-05 19:52:42.359 |
Context
2014-09-06
| ||
20:19 | Add support for delete operations to the ota extension. (check-in: f988234ba5 user: dan tags: ota-update) | |
2014-09-05
| ||
19:52 | Switch back to using a single database connection in sqlite3ota.c. (check-in: 3c2f4a0781 user: dan tags: ota-update) | |
19:31 | Reorganize the code in sqlite3ota.c in preparation for adding support for update and delete operations. (check-in: 98387f0569 user: dan tags: ota-update) | |
Changes
Changes to ext/ota/sqlite3ota.c.
︙ | ︙ | |||
31 32 33 34 35 36 37 | ** Or, if the main table is being written, a NULL value. ** ** "row" -> Number of rows for this object already processed ** ** "progress" -> total number of key/value b-tree operations performed ** so far as part of this ota update. */ | | | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | ** Or, if the main table is being written, a NULL value. ** ** "row" -> Number of rows for this object already processed ** ** "progress" -> total number of key/value b-tree operations performed ** so far as part of this ota update. */ #define OTA_CREATE_STATE "CREATE TABLE IF NOT EXISTS ota.ota_state" \ "(tbl, idx, row, progress)" typedef struct OtaState OtaState; typedef struct OtaObjIter OtaObjIter; typedef unsigned char u8; /* |
︙ | ︙ | |||
79 80 81 82 83 84 85 | sqlite3_stmt *pInsert; /* Statement for INSERT operations */ }; /* ** OTA handle. */ struct sqlite3ota { | < | < < | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | sqlite3_stmt *pInsert; /* Statement for INSERT operations */ }; /* ** OTA handle. */ struct sqlite3ota { sqlite3 *db; /* "main" -> target db, "ota" -> ota db */ char *zTarget; /* Path to target db */ int rc; /* Value returned by last ota_step() call */ char *zErrmsg; /* Error message if rc!=SQLITE_OK */ int nStep; /* Rows processed for current object */ OtaObjIter objiter; }; /* ** Prepare the SQL statement in buffer zSql against database handle db. ** If successful, set *ppStmt to point to the new statement and return |
︙ | ︙ | |||
258 259 260 261 262 263 264 | ** left in the OTA handle passed as the first argument. A copy of the ** error code is returned. */ static int otaObjIterFirst(sqlite3ota *p, OtaObjIter *pIter){ int rc; memset(pIter, 0, sizeof(OtaObjIter)); | | | | | | 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | ** left in the OTA handle passed as the first argument. A copy of the ** error code is returned. */ static int otaObjIterFirst(sqlite3ota *p, OtaObjIter *pIter){ int rc; memset(pIter, 0, sizeof(OtaObjIter)); rc = prepareAndCollectError(p->db, &pIter->pTblIter, &p->zErrmsg, "SELECT substr(name, 6) FROM ota.sqlite_master " "WHERE type='table' AND name LIKE 'data_%'" ); if( rc==SQLITE_OK ){ rc = prepareAndCollectError(p->db, &pIter->pIdxIter, &p->zErrmsg, "SELECT name FROM main.sqlite_master " "WHERE type='index' AND tbl_name = ?" ); } pIter->bCleanup = 1; p->rc = rc; return otaObjIterNext(p, pIter); |
︙ | ︙ | |||
321 322 323 324 325 326 327 | if( pIter->azTblCol==0 ){ sqlite3_stmt *pStmt; char *zSql; int nCol = 0; int bSeenPk = 0; int rc2; /* sqlite3_finalize() return value */ | | | | 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 | if( pIter->azTblCol==0 ){ sqlite3_stmt *pStmt; char *zSql; int nCol = 0; int bSeenPk = 0; int rc2; /* sqlite3_finalize() return value */ zSql = sqlite3_mprintf("PRAGMA main.table_info(%Q)", pIter->zTbl); p->rc = prepareFreeAndCollectError(p->db, &pStmt, &p->zErrmsg, zSql); while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ if( (nCol % 8)==0 ){ int nByte = sizeof(char*) * (nCol+8); char **azNew = (char**)sqlite3_realloc(pIter->azTblCol, nByte); u8 *abNew = (u8*)sqlite3_realloc(pIter->azTblCol, nCol+8); if( azNew ) pIter->azTblCol = azNew; |
︙ | ︙ | |||
425 426 427 428 429 430 431 | if( zIdx ){ int *aiCol; /* Column map */ /* Create the index writer */ if( p->rc==SQLITE_OK ){ p->rc = sqlite3_index_writer( | | | | | | | > | | 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 | if( zIdx ){ int *aiCol; /* Column map */ /* Create the index writer */ if( p->rc==SQLITE_OK ){ p->rc = sqlite3_index_writer( p->db, 0, zIdx, &pIter->pInsert, &aiCol, &pIter->nCol ); } /* Create the SELECT statement to read keys in sorted order */ zCollist = otaObjIterGetCollist(p, pIter, pIter->nCol, aiCol); if( p->rc==SQLITE_OK ){ p->rc = prepareFreeAndCollectError(p->db, &pIter->pSelect, pz, sqlite3_mprintf( "SELECT %s FROM ota.'data_%q' ORDER BY %s%s", zCollist, pIter->zTbl, zCollist, zLimit ) ); } }else{ char *zBindings = otaObjIterGetBindlist(p, pIter->nTblCol); zCollist = otaObjIterGetCollist(p, pIter, pIter->nTblCol, 0); pIter->nCol = pIter->nTblCol; /* Create the SELECT statement to read keys from data_xxx */ if( p->rc==SQLITE_OK ){ p->rc = prepareFreeAndCollectError(p->db, &pIter->pSelect, pz, sqlite3_mprintf( "SELECT %s FROM ota.'data_%q'%s", zCollist, pIter->zTbl, zLimit) ); } /* Create the INSERT statement to write to the target PK b-tree */ if( p->rc==SQLITE_OK ){ p->rc = prepareFreeAndCollectError(p->db, &pIter->pInsert, pz, sqlite3_mprintf( "INSERT INTO main.%Q(%s) VALUES(%s)", pIter->zTbl, zCollist, zBindings ) ); } sqlite3_free(zBindings); } sqlite3_free(zCollist); sqlite3_free(zLimit); |
︙ | ︙ | |||
530 531 532 533 534 535 536 | if( p->rc==SQLITE_OK && pIter->zTbl==0 ){ p->rc = SQLITE_DONE; } } return p->rc; } | > > > > > > > > > > | > > | > | > | | > > < | < | < < < < < < < < < < < | | | 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 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 | if( p->rc==SQLITE_OK && pIter->zTbl==0 ){ p->rc = SQLITE_DONE; } } return p->rc; } /* ** Argument zFmt is a sqlite3_mprintf() style format string. The trailing ** arguments are the usual subsitution values. This function performs ** the printf() style substitutions and executes the result as an SQL ** statement on the OTA handles database. ** ** If an error occurs, an error code and error message is stored in the ** OTA handle. If an error has already occurred when this function is ** called, it is a no-op. */ static int otaMPrintfExec(sqlite3ota *p, const char *zFmt, ...){ va_list ap; va_start(ap, zFmt); if( p->rc==SQLITE_OK ){ char *zSql = sqlite3_vmprintf(zFmt, ap); if( zSql==0 ){ p->rc = SQLITE_NOMEM; }else{ p->rc = sqlite3_exec(p->db, zSql, 0, 0, &p->zErrmsg); sqlite3_free(zSql); } } va_end(ap); return p->rc; } static void otaSaveTransactionState(sqlite3ota *p){ otaMPrintfExec(p, "INSERT OR REPLACE INTO ota.ota_state(rowid, tbl, idx, row, progress)" "VALUES(1, %Q, %Q, %d, NULL)", p->objiter.zTbl, p->objiter.zIdx, p->nStep ); } /* ** Allocate an OtaState object and load the contents of the ota_state ** table into it. Return a pointer to the new object. It is the ** responsibility of the caller to eventually free the object using ** sqlite3_free(). ** ** If an error occurs, leave an error code and message in the ota handle ** and return NULL. */ static OtaState *otaLoadState(sqlite3ota *p){ const char *zSelect = "SELECT tbl, idx, row, progress FROM ota.ota_state"; OtaState *pRet = 0; sqlite3_stmt *pStmt; int rc; assert( p->rc==SQLITE_OK ); rc = prepareAndCollectError(p->db, &pStmt, &p->zErrmsg, zSelect); if( rc==SQLITE_OK ){ if( sqlite3_step(pStmt)==SQLITE_ROW ){ const char *zIdx = (const char*)sqlite3_column_text(pStmt, 1); const char *zTbl = (const char*)sqlite3_column_text(pStmt, 0); int nIdx = zIdx ? (strlen(zIdx) + 1) : 0; int nTbl = strlen(zTbl) + 1; int nByte = sizeof(OtaState) + nTbl + nIdx; |
︙ | ︙ | |||
696 697 698 699 700 701 702 | if( p ){ OtaState *pState = 0; /* Open the target database */ memset(p, 0, sizeof(sqlite3ota)); p->zTarget = (char*)&p[1]; memcpy(p->zTarget, zTarget, nTarget+1); | | > > > | | | < < < < < | 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 | if( p ){ OtaState *pState = 0; /* Open the target database */ memset(p, 0, sizeof(sqlite3ota)); p->zTarget = (char*)&p[1]; memcpy(p->zTarget, zTarget, nTarget+1); p->rc = sqlite3_open(zTarget, &p->db); if( p->rc ){ p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db)); } otaMPrintfExec(p, "ATTACH %Q AS ota", zOta); /* If it has not already been created, create the ota_state table */ if( p->rc==SQLITE_OK ){ p->rc = sqlite3_exec(p->db, OTA_CREATE_STATE, 0, 0, &p->zErrmsg); } if( p->rc==SQLITE_OK ){ pState = otaLoadState(p); if( pState && pState->zTbl==0 ){ otaDeleteOalFile(p); } } if( p->rc==SQLITE_OK ){ const char *zScript = "PRAGMA journal_mode=off;" "PRAGMA pager_ota_mode=1;" "PRAGMA ota_mode=1;" "BEGIN IMMEDIATE;" ; p->rc = sqlite3_exec(p->db, zScript, 0, 0, &p->zErrmsg); } /* Point the object iterator at the first object */ if( p->rc==SQLITE_OK ){ p->rc = otaObjIterFirst(p, &p->objiter); } |
︙ | ︙ | |||
762 763 764 765 766 767 768 | } /* Close all open statement handles. */ otaObjIterFinalize(&p->objiter); /* Commit the transaction to the *-oal file. */ if( p->rc==SQLITE_OK || p->rc==SQLITE_DONE ){ | | < < < | < | 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 | } /* Close all open statement handles. */ otaObjIterFinalize(&p->objiter); /* Commit the transaction to the *-oal file. */ if( p->rc==SQLITE_OK || p->rc==SQLITE_DONE ){ rc = sqlite3_exec(p->db, "COMMIT", 0, 0, &p->zErrmsg); if( rc!=SQLITE_OK ) p->rc = rc; } /* Close the open database handles */ sqlite3_close(p->db); /* If the OTA has been completely applied and no error occurred, move ** the *-oal file to *-wal. */ if( p->rc==SQLITE_DONE ){ otaMoveOalFile(p); } |
︙ | ︙ |