SQLite

Check-in [b9b38cb8e2]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add OP_Affinity opcodes to the VMs generated by sqlite3_index_writer().
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | ota-update
Files: files | file ages | folders
SHA1: b9b38cb8e21826ddfb4c87a1f166ad33c3c7b6eb
User & Date: dan 2014-09-15 10:44:24.271
Context
2014-09-15
12:18
Have the sqlite3_index_writer() VMs check that the final values of records inserted into indexes on rowid tables are integers. (check-in: cca376bff3 user: dan tags: ota-update)
10:44
Add OP_Affinity opcodes to the VMs generated by sqlite3_index_writer(). (check-in: b9b38cb8e2 user: dan tags: ota-update)
2014-09-08
17:50
Add support for update statements to sqlite3ota.c. (check-in: e109b27e4d user: dan tags: ota-update)
Changes
Unified Diff Ignore Whitespace Patch
Added ext/ota/ota3.test.












































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 2014 August 30
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#

set testdir [file join [file dirname $argv0] .. .. test]
source $testdir/tester.tcl
set ::testprefix ota3


# Run the OTA in file $ota on target database $target until completion.
#
proc run_ota {target ota} {
  sqlite3ota ota $target $ota
  while { [ota step]=="SQLITE_OK" } {}
  ota close
}

forcedelete test.db-oal ota.db

#--------------------------------------------------------------------
# Test that for an OTA to be applied, no corruption results if the
# affinities on the source and target table do not match.
#
do_execsql_test 1.0 {
  CREATE TABLE x1(a INTEGER PRIMARY KEY, b TEXT, c REAL);
  CREATE INDEX i1 ON x1(b, c);
} {}

do_test 1.1 {
  sqlite3 db2 ota.db
  db2 eval {
    CREATE TABLE data_x1(a, b, c, ota_control);
    INSERT INTO data_x1 VALUES(1, '123', '123', 0);
    INSERT INTO data_x1 VALUES(2, 123, 123, 0);
  }
  db2 close
  run_ota test.db ota.db
} {SQLITE_DONE}

do_execsql_test 1.2 {
  PRAGMA integrity_check;
} {ok}



finish_test
Changes to src/vdbeblob.c.
474
475
476
477
478
479
480

481
482
483
484
485
486
487
  Parse *pParse = 0;
  Index *pIdx = 0;                /* The index to write to */
  Table *pTab;
  int i;                          /* Used to iterate through index columns */
  Vdbe *v = 0;
  int regRec;                     /* Register to assemble record in */
  int *aiCol = 0;


  sqlite3_mutex_enter(db->mutex);
  sqlite3BtreeEnterAll(db);

  /* Allocate the parse context */
  pParse = sqlite3StackAllocRaw(db, sizeof(*pParse));
  if( !pParse ) goto index_writer_out;







>







474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
  Parse *pParse = 0;
  Index *pIdx = 0;                /* The index to write to */
  Table *pTab;
  int i;                          /* Used to iterate through index columns */
  Vdbe *v = 0;
  int regRec;                     /* Register to assemble record in */
  int *aiCol = 0;
  const char *zAffinity = 0;      /* Affinity string for the current index */

  sqlite3_mutex_enter(db->mutex);
  sqlite3BtreeEnterAll(db);

  /* Allocate the parse context */
  pParse = sqlite3StackAllocRaw(db, sizeof(*pParse));
  if( !pParse ) goto index_writer_out;
495
496
497
498
499
500
501

502
503
504
505
506
507
508
  /* Find the index to write to */
  pIdx = sqlite3FindIndex(db, zIndex, "main");
  if( pIdx==0 ){
    sqlite3ErrorMsg(pParse, "no such index: %s", zIndex);
    goto index_writer_out;
  }
  pTab = pIdx->pTable;


  /* Populate the two output variables, *pnCol and *pnAiCol. */
  *pnCol = pIdx->nColumn;
  *paiCol = aiCol = sqlite3DbMallocZero(db, sizeof(int) * pIdx->nColumn);
  if( aiCol==0 ){
    rc = SQLITE_NOMEM;
    goto index_writer_out;







>







496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
  /* Find the index to write to */
  pIdx = sqlite3FindIndex(db, zIndex, "main");
  if( pIdx==0 ){
    sqlite3ErrorMsg(pParse, "no such index: %s", zIndex);
    goto index_writer_out;
  }
  pTab = pIdx->pTable;
  zAffinity = sqlite3IndexAffinityStr(v, pIdx);

  /* Populate the two output variables, *pnCol and *pnAiCol. */
  *pnCol = pIdx->nColumn;
  *paiCol = aiCol = sqlite3DbMallocZero(db, sizeof(int) * pIdx->nColumn);
  if( aiCol==0 ){
    rc = SQLITE_NOMEM;
    goto index_writer_out;
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
  pParse->nMem = pIdx->nColumn;
  for(i=1; i<=pIdx->nColumn; i++){
    sqlite3VdbeAddOp2(v, OP_Variable, i, i);
  }
  regRec = ++pParse->nMem;

  if( bDelete==0 ){
    sqlite3VdbeAddOp3(v, OP_MakeRecord, 1, pIdx->nColumn, regRec);

    /* If this is a UNIQUE index, check the constraint. */
    if( pIdx->onError ){
      int addr = sqlite3VdbeAddOp4Int(v, OP_NoConflict, 0, 0, 1, pIdx->nKeyCol);
      sqlite3UniqueConstraint(pParse, SQLITE_ABORT, pIdx);
      sqlite3VdbeJumpHere(v, addr);
    }

    /* Code the IdxInsert to write to the b-tree index. */
    sqlite3VdbeAddOp2(v, OP_IdxInsert, 0, regRec);
  }else{
    /* Code the IdxDelete to remove the entry from the b-tree index. */

    sqlite3VdbeAddOp3(v, OP_IdxDelete, 0, 1, pIdx->nColumn);
  }
  sqlite3FinishCoding(pParse);

index_writer_out:
  if( rc==SQLITE_OK && db->mallocFailed==0 ){
    *ppStmt = (sqlite3_stmt*)v;







|












>







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
  pParse->nMem = pIdx->nColumn;
  for(i=1; i<=pIdx->nColumn; i++){
    sqlite3VdbeAddOp2(v, OP_Variable, i, i);
  }
  regRec = ++pParse->nMem;

  if( bDelete==0 ){
    sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, pIdx->nColumn, regRec, zAffinity, 0);

    /* If this is a UNIQUE index, check the constraint. */
    if( pIdx->onError ){
      int addr = sqlite3VdbeAddOp4Int(v, OP_NoConflict, 0, 0, 1, pIdx->nKeyCol);
      sqlite3UniqueConstraint(pParse, SQLITE_ABORT, pIdx);
      sqlite3VdbeJumpHere(v, addr);
    }

    /* Code the IdxInsert to write to the b-tree index. */
    sqlite3VdbeAddOp2(v, OP_IdxInsert, 0, regRec);
  }else{
    /* Code the IdxDelete to remove the entry from the b-tree index. */
    sqlite3VdbeAddOp4(v, OP_Affinity, 0, pIdx->nColumn, 0, zAffinity, 0);
    sqlite3VdbeAddOp3(v, OP_IdxDelete, 0, 1, pIdx->nColumn);
  }
  sqlite3FinishCoding(pParse);

index_writer_out:
  if( rc==SQLITE_OK && db->mallocFailed==0 ){
    *ppStmt = (sqlite3_stmt*)v;