/ Check-in [d0e7cf4a]
Login

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

Overview
Comment:Change to five conflict resolution algorithms: ROLLBACK, ABORT, FAIL, IGNORE, and REPLACE. This checkin is code only. Documentation and tests are still needed. Also, ABORT is not fully implemented. (CVS 360)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:d0e7cf4a83e6abad7129bed356b7492dddaff474
User & Date: drh 2002-01-31 15:54:21
Context
2002-02-02
15:01
Checkpoint code added to the pager. Regression tests work but the new APIs have not been tested yet. (CVS 361) check-in: aaa53e11 user: drh tags: trunk
2002-01-31
15:54
Change to five conflict resolution algorithms: ROLLBACK, ABORT, FAIL, IGNORE, and REPLACE. This checkin is code only. Documentation and tests are still needed. Also, ABORT is not fully implemented. (CVS 360) check-in: d0e7cf4a user: drh tags: trunk
2002-01-30
16:17
Added ON CONFLICT support to COPY. Updates to documentation. Bug fixes. (CVS 359) check-in: cf1538d7 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to publish.sh.

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
..
65
66
67
68
69
70
71

































72
73
74

75
76
77
78
79
80
81
..
99
100
101
102
103
104
105

rm -f sqlite.bin.gz
gzip sqlite.bin

# Build the tclsqlite.so shared library for import into tclsh or wish
# under Linux
#
make target_source

cd tsrc

rm shell.c
TCLDIR=/home/drh/tcltk/8.2linux
TCLSTUBLIB=$TCLDIR/libtclstub8.2g.a
OPTS='-DUSE_TCL_STUBS=1 -DNDEBUG=1'
gcc -fPIC $OPTS -O2 -I. -I$TCLDIR -shared *.c $TCLSTUBLIB -o tclsqlite.so
strip tclsqlite.so
mv tclsqlite.so ..




cd ..
rm -f tclsqlite.so.gz
gzip tclsqlite.so


# Build the tclsqlite.dll shared library that can be imported into tclsh
# or wish on windows.
#
make target_source
cd tsrc
rm shell.c
................................................................................
     --driver-name i386-mingw32-gcc \
     --dlltool-name i386-mingw32-dlltool \
     --as i386-mingw32-as \
     --target i386-mingw32 \
     -dllname tclsqlite.dll -lmsvcrt *.o $TCLSTUBLIB
i386-mingw32-strip tclsqlite.dll
mv tclsqlite.dll ..

































cd ..
rm -f tclsqlite.zip
zip tclsqlite.zip tclsqlite.dll


# Build the sqlite.exe executable for windows.
#
make target_source
cd tsrc
rm tclsqlite.c
OPTS='-DSTATIC_BUILD=1 -DNDEBUG=1'
................................................................................

# Build the website
#
cp $srcdir/../historical/* .
rm -rf doc
make doc
ln sqlite.bin.gz sqlite.zip sqlite*.tar.gz tclsqlite.so.gz tclsqlite.zip doc








>

>







>
>
>
>

|

>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|

>







 







>
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
55
..
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
...
140
141
142
143
144
145
146
147
rm -f sqlite.bin.gz
gzip sqlite.bin

# Build the tclsqlite.so shared library for import into tclsh or wish
# under Linux
#
make target_source
rm sqlite_source.zip
cd tsrc
zip ../sqlite_source.zip *
rm shell.c
TCLDIR=/home/drh/tcltk/8.2linux
TCLSTUBLIB=$TCLDIR/libtclstub8.2g.a
OPTS='-DUSE_TCL_STUBS=1 -DNDEBUG=1'
gcc -fPIC $OPTS -O2 -I. -I$TCLDIR -shared *.c $TCLSTUBLIB -o tclsqlite.so
strip tclsqlite.so
mv tclsqlite.so ..
rm tclsqlite.c
gcc -fPIC -DNDEBUG=1 -O2 -I. -shared *.c -o sqlite.so
strip sqlite.so
mv sqlite.so ..
cd ..
rm -f tclsqlite.so.gz sqlite.so.gz
gzip tclsqlite.so
gzip sqlite.so

# Build the tclsqlite.dll shared library that can be imported into tclsh
# or wish on windows.
#
make target_source
cd tsrc
rm shell.c
................................................................................
     --driver-name i386-mingw32-gcc \
     --dlltool-name i386-mingw32-dlltool \
     --as i386-mingw32-as \
     --target i386-mingw32 \
     -dllname tclsqlite.dll -lmsvcrt *.o $TCLSTUBLIB
i386-mingw32-strip tclsqlite.dll
mv tclsqlite.dll ..
rm tclsqlite.o
cat >sqlite.def <<\END_OF_FILE
EXPORTS
sqlite_open
sqlite_close
sqlite_exec
sqlite_last_insert_rowid
sqlite_error_string
sqlite_interrupt
sqlite_complete
sqlite_busy_handler
sqlite_busy_timeout
sqlite_get_table
sqlite_free_table
sqlite_mprintf
sqlite_vmprintf
sqlite_exec_printf
sqlite_exec_vprintf
sqlite_get_table_printf
sqlite_get_table_vprintf
sqliteMalloc
sqliteFree
sqliteRealloc
END_OF_FILE
i386-mingw32-dllwrap \
     --def sqlite.def -v --export-all \
     --driver-name i386-mingw32-gcc \
     --dlltool-name i386-mingw32-dlltool \
     --as i386-mingw32-as \
     --target i386-mingw32 \
     -dllname sqlite.dll -lmsvcrt *.o
i386-mingw32-strip sqlite.dll
mv sqlite.dll sqlite.def ..
cd ..
rm -f tclsqlite.zip sqlitedll.zip
zip tclsqlite.zip tclsqlite.dll
zip sqlitedll.zip sqlite.dll sqlite.def

# Build the sqlite.exe executable for windows.
#
make target_source
cd tsrc
rm tclsqlite.c
OPTS='-DSTATIC_BUILD=1 -DNDEBUG=1'
................................................................................

# Build the website
#
cp $srcdir/../historical/* .
rm -rf doc
make doc
ln sqlite.bin.gz sqlite.zip sqlite*.tar.gz tclsqlite.so.gz tclsqlite.zip doc
ln sqlitedll.zip sqlite.so.gz sqlite_source.zip doc

Changes to src/build.c.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
...
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
...
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
...
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
....
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
....
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
....
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
....
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
....
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
....
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
....
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
....
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
1520
1521
1522
1523
1524
....
1528
1529
1530
1531
1532
1533
1534

1535





































1536
1537
1538
1539
1540
1541
1542
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.69 2002/01/30 16:17:24 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 
................................................................................
      pParse->nErr++;
      return;
    }
    if( db->flags & SQLITE_InTrans ){
      rc = sqliteBtreeBeginTrans(db->pBeTemp);
      if( rc!=SQLITE_OK ){
        sqliteSetNString(&pParse->zErrMsg, "unable to get a write lock on "
          "the temporary datbase file", 0);
        pParse->nErr++;
        return;
      }
    }
  }

  /* Make sure the new table name does not collide with an existing
................................................................................
  pTable->aCol = 0;
  pTable->iPKey = -1;
  pTable->pIndex = 0;
  pTable->isTemp = isTemp;
  if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
  pParse->pNewTable = pTable;
  if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
      sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
      pParse->schemaVerified = 1;
    }
    if( !isTemp ){
      sqliteVdbeAddOp(v, OP_SetCookie, db->file_format, 1);
      sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
      sqliteVdbeChangeP3(v, -1, MASTER_NAME, P3_STATIC);
    }
  }
}
................................................................................
      sqliteVdbeChangeP3(v, addr, pParse->sFirstToken.z, n);
      sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
      sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
      changeCookie(db);
      sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0);
      sqliteVdbeAddOp(v, OP_Close, 0, 0);
    }
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Commit, 0, 0);
    }
  }
}

/*
** Given a token, look up a table with that name.  If not found, leave
** an error for the parser to find and return NULL.
*/
................................................................................
      { OP_Ne,         0, ADDR(8),  0},
      { OP_Delete,     0, 0,        0},
      { OP_Next,       0, ADDR(4),  0}, /* 8 */
      { OP_SetCookie,  0, 0,        0}, /* 9 */
      { OP_Close,      0, 0,        0},
    };
    Index *pIdx;
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
      sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
      pParse->schemaVerified = 1;
    }
    if( !pTable->isTemp ){
      base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
      sqliteVdbeChangeP3(v, base+2, pTable->zName, P3_STATIC);
      changeCookie(db);
      sqliteVdbeChangeP1(v, base+9, db->next_cookie);
    }
    sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->isTemp);
    for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){
      sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pTable->isTemp);
    }
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Commit, 0, 0);
    }
  }

  /* Move the table (and all its indices) to the pending DROP queue.
  ** Or, if the table was never committed, just delete it.  If the table
  ** has been committed and is placed on the pending DROP queue, then the
  ** delete will occur when sqliteCommitInternalChanges() executes.
  **
................................................................................
    int i;
    int addr;
    int isTemp = pTab->isTemp;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) goto exit_create_index;
    if( pTable!=0 ){
      if( (db->flags & SQLITE_InTrans)==0 ){
        sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
        sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
        pParse->schemaVerified = 1;
      }
      if( !isTemp ){
        sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
        sqliteVdbeChangeP3(v, -1, MASTER_NAME, P3_STATIC);
      }
    }
    if( !isTemp ){
      sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
................................................................................
    }
    if( pTable!=0 ){
      if( !isTemp ){
        changeCookie(db);
        sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0);
        sqliteVdbeAddOp(v, OP_Close, 0, 0);
      }
      if( (db->flags & SQLITE_InTrans)==0 ){
        sqliteVdbeAddOp(v, OP_Commit, 0, 0);
      }
    }
  }

  /* Clean up before exiting */
exit_create_index:
  sqliteIdListDelete(pList);
  sqliteFree(zName);
................................................................................
      { OP_Delete,     0, 0,       0}, /* 9 */
      { OP_SetCookie,  0, 0,       0}, /* 10 */
      { OP_Close,      0, 0,       0},
    };
    int base;
    Table *pTab = pIndex->pTable;

    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
      sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
      pParse->schemaVerified = 1;
    }
    if( !pTab->isTemp ){
      base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
      sqliteVdbeChangeP3(v, base+2, pIndex->zName, P3_STATIC);
      changeCookie(db);
      sqliteVdbeChangeP1(v, base+10, db->next_cookie);
    }
    sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pTab->isTemp);
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Commit, 0, 0);
    }
  }

  /* Move the index onto the pending DROP queue.  Or, if the index was
  ** never committed, just delete it.  Indices on the pending DROP queue
  ** get deleted by sqliteCommitInternalChanges() when the user executes
  ** a COMMIT.  Or if a rollback occurs, the elements of the DROP queue
  ** are moved back into the main hash table.
................................................................................
  Token *pTableName,   /* The name of the table into which we will insert */
  Token *pFilename,    /* The file from which to obtain information */
  Token *pDelimiter,   /* Use this as the field delimiter */
  int onError          /* What to do if a constraint fails */
){
  Table *pTab;
  char *zTab;
  int i, j;
  Vdbe *v;
  int addr, end;
  Index *pIdx;
  sqlite *db = pParse->db;

  zTab = sqliteTableNameFromToken(pTableName);
  if( sqlite_malloc_failed || zTab==0 ) goto copy_cleanup;
................................................................................
        " may not be modified", 0);
    pParse->nErr++;
    goto copy_cleanup;
  }
  v = sqliteGetVdbe(pParse);
  if( v ){
    int openOp;
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
      sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
      pParse->schemaVerified = 1;
    }
    addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0);
    sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n);
    sqliteVdbeDequoteP3(v, addr);
    openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite;
    sqliteVdbeAddOp(v, openOp, 0, pTab->tnum);
    sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
    for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
................................................................................
    sqliteCompleteInsertion(pParse, pTab, 0, 0, 0, 0);
    if( (db->flags & SQLITE_CountRows)!=0 ){
      sqliteVdbeAddOp(v, OP_AddImm, 1, 0);  /* Increment row count */
    }
    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
    sqliteVdbeResolveLabel(v, end);
    sqliteVdbeAddOp(v, OP_Noop, 0, 0);
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Commit, 0, 0);
    }
    if( db->flags & SQLITE_CountRows ){
      sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
      sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
      sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
      sqliteVdbeAddOp(v, OP_Callback, 1, 0);
    }
  }
................................................................................
    && sqliteFindTable(db, zName)==0 ){
    sqliteSetString(&pParse->zErrMsg, "no such table or index: ", zName, 0);
    pParse->nErr++;
    goto vacuum_cleanup;
  }
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto vacuum_cleanup;
  if( (db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
    sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
    pParse->schemaVerified = 1;
  }
  if( zName ){
    sqliteVdbeAddOp(v, OP_Reorganize, 0, 0);
    sqliteVdbeChangeP3(v, -1, zName, strlen(zName));
  }else{
    Table *pTab;
    Index *pIdx;
    HashElem *pE;
................................................................................
      sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
        sqliteVdbeAddOp(v, OP_Reorganize, 0, 0);
        sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
      }
    }
  }
  if( (db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Commit, 0, 0);
  }

vacuum_cleanup:
  sqliteFree(zName);
  return;
}

/*
** Begin a transaction
*/
void sqliteBeginTransaction(Parse *pParse){
  sqlite *db;
  Vdbe *v;

  if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;
  if( pParse->nErr || sqlite_malloc_failed ) return;
  if( db->flags & SQLITE_InTrans ) return;
  v = sqliteGetVdbe(pParse);
  if( v ){
    sqliteVdbeAddOp(v, OP_Transaction, 1, 0);
    sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
    pParse->schemaVerified = 1;
  }
  db->flags |= SQLITE_InTrans;

}

/*
** Commit a transaction
*/
void sqliteCommitTransaction(Parse *pParse){
  sqlite *db;
  Vdbe *v;

  if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;
  if( pParse->nErr || sqlite_malloc_failed ) return;
  if( (db->flags & SQLITE_InTrans)==0 ) return;
  v = sqliteGetVdbe(pParse);
  if( v ){
    sqliteVdbeAddOp(v, OP_Commit, 0, 0);
  }
  db->flags &= ~SQLITE_InTrans;


}

/*
** Rollback a transaction
*/
void sqliteRollbackTransaction(Parse *pParse){
  sqlite *db;
................................................................................
  if( pParse->nErr || sqlite_malloc_failed ) return;
  if( (db->flags & SQLITE_InTrans)==0 ) return;
  v = sqliteGetVdbe(pParse);
  if( v ){
    sqliteVdbeAddOp(v, OP_Rollback, 0, 0);
  }
  db->flags &= ~SQLITE_InTrans;

}






































/*
** Interpret the given string as a boolean value.
*/
static int getBoolean(char *z){
  static char *azTrue[] = { "yes", "on", "true" };
  int i;







|







 







|







 







|
<
<
<
<







 







|
<
<







 







|
<
<
<
<










|
<
<







 







|
<
<
<
<







 







|
<
<







 







|
<
<
<
<







|
<
<







 







|







 







|
<
<
<
<







 







|
<
<







 







|
<
<
<
<







 







|
<
<









|

<




|
<
<
<
<
<

>







<




<
<
<
<

>
>







 







>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
...
470
471
472
473
474
475
476
477




478
479
480
481
482
483
484
...
730
731
732
733
734
735
736
737


738
739
740
741
742
743
744
...
792
793
794
795
796
797
798
799




800
801
802
803
804
805
806
807
808
809
810


811
812
813
814
815
816
817
....
1041
1042
1043
1044
1045
1046
1047
1048




1049
1050
1051
1052
1053
1054
1055
....
1098
1099
1100
1101
1102
1103
1104
1105


1106
1107
1108
1109
1110
1111
1112
....
1151
1152
1153
1154
1155
1156
1157
1158




1159
1160
1161
1162
1163
1164
1165
1166


1167
1168
1169
1170
1171
1172
1173
....
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
....
1334
1335
1336
1337
1338
1339
1340
1341




1342
1343
1344
1345
1346
1347
1348
....
1379
1380
1381
1382
1383
1384
1385
1386


1387
1388
1389
1390
1391
1392
1393
....
1416
1417
1418
1419
1420
1421
1422
1423




1424
1425
1426
1427
1428
1429
1430
....
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
....
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
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.70 2002/01/31 15:54:22 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 
................................................................................
      pParse->nErr++;
      return;
    }
    if( db->flags & SQLITE_InTrans ){
      rc = sqliteBtreeBeginTrans(db->pBeTemp);
      if( rc!=SQLITE_OK ){
        sqliteSetNString(&pParse->zErrMsg, "unable to get a write lock on "
          "the temporary database file", 0);
        pParse->nErr++;
        return;
      }
    }
  }

  /* Make sure the new table name does not collide with an existing
................................................................................
  pTable->aCol = 0;
  pTable->iPKey = -1;
  pTable->pIndex = 0;
  pTable->isTemp = isTemp;
  if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
  pParse->pNewTable = pTable;
  if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){
    sqliteBeginWriteOperation(pParse);




    if( !isTemp ){
      sqliteVdbeAddOp(v, OP_SetCookie, db->file_format, 1);
      sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
      sqliteVdbeChangeP3(v, -1, MASTER_NAME, P3_STATIC);
    }
  }
}
................................................................................
      sqliteVdbeChangeP3(v, addr, pParse->sFirstToken.z, n);
      sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
      sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
      changeCookie(db);
      sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0);
      sqliteVdbeAddOp(v, OP_Close, 0, 0);
    }
    sqliteEndWriteOperation(pParse);


  }
}

/*
** Given a token, look up a table with that name.  If not found, leave
** an error for the parser to find and return NULL.
*/
................................................................................
      { OP_Ne,         0, ADDR(8),  0},
      { OP_Delete,     0, 0,        0},
      { OP_Next,       0, ADDR(4),  0}, /* 8 */
      { OP_SetCookie,  0, 0,        0}, /* 9 */
      { OP_Close,      0, 0,        0},
    };
    Index *pIdx;
    sqliteBeginWriteOperation(pParse);




    if( !pTable->isTemp ){
      base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
      sqliteVdbeChangeP3(v, base+2, pTable->zName, P3_STATIC);
      changeCookie(db);
      sqliteVdbeChangeP1(v, base+9, db->next_cookie);
    }
    sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->isTemp);
    for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){
      sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pTable->isTemp);
    }
    sqliteEndWriteOperation(pParse);


  }

  /* Move the table (and all its indices) to the pending DROP queue.
  ** Or, if the table was never committed, just delete it.  If the table
  ** has been committed and is placed on the pending DROP queue, then the
  ** delete will occur when sqliteCommitInternalChanges() executes.
  **
................................................................................
    int i;
    int addr;
    int isTemp = pTab->isTemp;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) goto exit_create_index;
    if( pTable!=0 ){
      sqliteBeginWriteOperation(pParse);




      if( !isTemp ){
        sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
        sqliteVdbeChangeP3(v, -1, MASTER_NAME, P3_STATIC);
      }
    }
    if( !isTemp ){
      sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
................................................................................
    }
    if( pTable!=0 ){
      if( !isTemp ){
        changeCookie(db);
        sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0);
        sqliteVdbeAddOp(v, OP_Close, 0, 0);
      }
      sqliteEndWriteOperation(pParse);


    }
  }

  /* Clean up before exiting */
exit_create_index:
  sqliteIdListDelete(pList);
  sqliteFree(zName);
................................................................................
      { OP_Delete,     0, 0,       0}, /* 9 */
      { OP_SetCookie,  0, 0,       0}, /* 10 */
      { OP_Close,      0, 0,       0},
    };
    int base;
    Table *pTab = pIndex->pTable;

    sqliteBeginWriteOperation(pParse);




    if( !pTab->isTemp ){
      base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
      sqliteVdbeChangeP3(v, base+2, pIndex->zName, P3_STATIC);
      changeCookie(db);
      sqliteVdbeChangeP1(v, base+10, db->next_cookie);
    }
    sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pTab->isTemp);
    sqliteEndWriteOperation(pParse);


  }

  /* Move the index onto the pending DROP queue.  Or, if the index was
  ** never committed, just delete it.  Indices on the pending DROP queue
  ** get deleted by sqliteCommitInternalChanges() when the user executes
  ** a COMMIT.  Or if a rollback occurs, the elements of the DROP queue
  ** are moved back into the main hash table.
................................................................................
  Token *pTableName,   /* The name of the table into which we will insert */
  Token *pFilename,    /* The file from which to obtain information */
  Token *pDelimiter,   /* Use this as the field delimiter */
  int onError          /* What to do if a constraint fails */
){
  Table *pTab;
  char *zTab;
  int i;
  Vdbe *v;
  int addr, end;
  Index *pIdx;
  sqlite *db = pParse->db;

  zTab = sqliteTableNameFromToken(pTableName);
  if( sqlite_malloc_failed || zTab==0 ) goto copy_cleanup;
................................................................................
        " may not be modified", 0);
    pParse->nErr++;
    goto copy_cleanup;
  }
  v = sqliteGetVdbe(pParse);
  if( v ){
    int openOp;
    sqliteBeginWriteOperation(pParse);




    addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0);
    sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n);
    sqliteVdbeDequoteP3(v, addr);
    openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite;
    sqliteVdbeAddOp(v, openOp, 0, pTab->tnum);
    sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
    for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
................................................................................
    sqliteCompleteInsertion(pParse, pTab, 0, 0, 0, 0);
    if( (db->flags & SQLITE_CountRows)!=0 ){
      sqliteVdbeAddOp(v, OP_AddImm, 1, 0);  /* Increment row count */
    }
    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
    sqliteVdbeResolveLabel(v, end);
    sqliteVdbeAddOp(v, OP_Noop, 0, 0);
    sqliteEndWriteOperation(pParse);


    if( db->flags & SQLITE_CountRows ){
      sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
      sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
      sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
      sqliteVdbeAddOp(v, OP_Callback, 1, 0);
    }
  }
................................................................................
    && sqliteFindTable(db, zName)==0 ){
    sqliteSetString(&pParse->zErrMsg, "no such table or index: ", zName, 0);
    pParse->nErr++;
    goto vacuum_cleanup;
  }
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto vacuum_cleanup;
  sqliteBeginWriteOperation(pParse);




  if( zName ){
    sqliteVdbeAddOp(v, OP_Reorganize, 0, 0);
    sqliteVdbeChangeP3(v, -1, zName, strlen(zName));
  }else{
    Table *pTab;
    Index *pIdx;
    HashElem *pE;
................................................................................
      sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
        sqliteVdbeAddOp(v, OP_Reorganize, 0, 0);
        sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
      }
    }
  }
  sqliteEndWriteOperation(pParse);



vacuum_cleanup:
  sqliteFree(zName);
  return;
}

/*
** Begin a transaction
*/
void sqliteBeginTransaction(Parse *pParse, int onError){
  sqlite *db;


  if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;
  if( pParse->nErr || sqlite_malloc_failed ) return;
  if( db->flags & SQLITE_InTrans ) return;
  sqliteBeginWriteOperation(pParse);





  db->flags |= SQLITE_InTrans;
  db->onError = onError;
}

/*
** Commit a transaction
*/
void sqliteCommitTransaction(Parse *pParse){
  sqlite *db;


  if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;
  if( pParse->nErr || sqlite_malloc_failed ) return;
  if( (db->flags & SQLITE_InTrans)==0 ) return;




  db->flags &= ~SQLITE_InTrans;
  sqliteEndWriteOperation(pParse);
  db->onError = OE_Default;
}

/*
** Rollback a transaction
*/
void sqliteRollbackTransaction(Parse *pParse){
  sqlite *db;
................................................................................
  if( pParse->nErr || sqlite_malloc_failed ) return;
  if( (db->flags & SQLITE_InTrans)==0 ) return;
  v = sqliteGetVdbe(pParse);
  if( v ){
    sqliteVdbeAddOp(v, OP_Rollback, 0, 0);
  }
  db->flags &= ~SQLITE_InTrans;
  db->onError = OE_Default;
}

/*
** Generate VDBE code that prepares for doing an operation that
** might change the database.  If we are in the middle of a transaction,
** then this sets a checkpoint.  If we are not in a transaction, then
** start a transaction.
*/
void sqliteBeginWriteOperation(Parse *pParse){
  Vdbe *v;
  v = sqliteGetVdbe(pParse);
  if( v==0 ) return;
  if( pParse->db->flags & SQLITE_InTrans ){
    /* sqliteVdbeAddOp(v, OP_CheckPoint, 0, 0); */
  }else{
    sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
    sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0);
    pParse->schemaVerified = 1;
  }
}

/*
** Generate code that concludes an operation that may have changed
** the database.  This is a companion function to BeginWriteOperation().
** If a transaction was started, then commit it.  If a checkpoint was
** started then commit that.
*/
void sqliteEndWriteOperation(Parse *pParse){
  Vdbe *v;
  v = sqliteGetVdbe(pParse);
  if( v==0 ) return;
  if( pParse->db->flags & SQLITE_InTrans ){
    /* Do Nothing */
  }else{
    sqliteVdbeAddOp(v, OP_Commit, 0, 0);
  }
}


/*
** Interpret the given string as a boolean value.
*/
static int getBoolean(char *z){
  static char *azTrue[] = { "yes", "on", "true" };
  int i;

Changes to src/delete.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
...
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.25 2002/01/29 23:07:02 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process a DELETE FROM statement.
*/
void sqliteDeleteFrom(
................................................................................
    }
  }

  /* Begin generating code.
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto delete_from_cleanup;
  if( (db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
    sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
    pParse->schemaVerified = 1;
  }

  /* Initialize the counter of the number of rows deleted, if
  ** we are counting rows.
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_Integer, 0, 0);
  }
................................................................................
    end = sqliteVdbeMakeLabel(v);
    addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
    sqliteGenerateRowDelete(v, pTab, base);
    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
    sqliteVdbeResolveLabel(v, end);
    sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
  }
  if( (db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Commit, 0, 0);
  }

  /*
  ** Return the number of rows that were deleted.
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
    sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);







|







 







|
<
<
<
<







 







|
<
<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
78
79
80
81
82
83
84
85




86
87
88
89
90
91
92
...
148
149
150
151
152
153
154
155


156
157
158
159
160
161
162
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.26 2002/01/31 15:54:22 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process a DELETE FROM statement.
*/
void sqliteDeleteFrom(
................................................................................
    }
  }

  /* Begin generating code.
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto delete_from_cleanup;
  sqliteBeginWriteOperation(pParse);





  /* Initialize the counter of the number of rows deleted, if
  ** we are counting rows.
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_Integer, 0, 0);
  }
................................................................................
    end = sqliteVdbeMakeLabel(v);
    addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
    sqliteGenerateRowDelete(v, pTab, base);
    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
    sqliteVdbeResolveLabel(v, end);
    sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
  }
  sqliteEndWriteOperation(pParse);



  /*
  ** Return the number of rows that were deleted.
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
    sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);

Changes to src/insert.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
...
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336










337
338
339
340
341
342
343
...
344
345
346
347
348
349
350
351
352
353

354
355
356
357
358
359
360
...
386
387
388
389
390
391
392



393
394
395
396
397
398
399
400
401
402
403
404


405
406
407
408
409
410
411

412

413
414
415
416
417
418
419
420
...
437
438
439
440
441
442
443


444
445

446

447
448
449
450
451
452
453
454
...
475
476
477
478
479
480
481


482
483
484
485

486

487
488
489
490
491
492
493
494
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.38 2002/01/30 16:17:24 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)
................................................................................
    goto insert_cleanup;
  }

  /* Allocate a VDBE
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto insert_cleanup;
  if( (db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
    sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
    pParse->schemaVerified = 1;
  }

  /* Figure out how many columns of data are supplied.  If the data
  ** is coming from a SELECT statement, then this step has to generate
  ** all the code to implement the SELECT statement and leave the data
  ** in a temporary table.  If data is coming from an expression list,
  ** then we just have to count the number of expressions.
  */
................................................................................
    sqliteVdbeResolveLabel(v, iBreak);
    sqliteVdbeAddOp(v, OP_Close, srcTab, 0);
  }
  sqliteVdbeAddOp(v, OP_Close, base, 0);
  for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
    sqliteVdbeAddOp(v, OP_Close, idx+base, 0);
  }
  if( (db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Commit, 0, 0);
  }

  /*
  ** Return the number of rows inserted.
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
    sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
................................................................................
**    3.  The data in the first column of the entry after the update.
**
**    i.  Data from middle columns...
**
**    N.  The data in the last column of the entry after the update.
**
** The old recno shown as entry (1) above is omitted unless both isUpdate
** and recnoChng are both 1.  isUpdate is true for UPDATEs and false for
** INSERTs and recnoChng is ture if the record number is being changed.
**
** The code generated by this routine pushes additional entries onto
** the stack which are the keys for new index entries for the new record.
** The order of index keys is the same as the order of the indices on
** the pTable->pIndex list.  A key is only created for index i if 
** aIdxUsed!=0 and aIdxUsed[i]!=0.
**
** This routine also generates code to check constraints.  NOT NULL,
** CHECK, and UNIQUE constraints are all checked.  If a constraint fails,
** then the appropriate action is performed.  The default action is to
** execute OP_Halt to abort the transaction and cause sqlite_exec() to
** return SQLITE_CONSTRAINT.  This is the so-called "ABORT" action.
** Other actions are REPLACE and IGNORE.  The following table summarizes
** what happens.
**
**  Constraint type  Action       What Happens
**  ---------------  ----------   ----------------------------------------
**  any              ABORT        The current transaction is rolled back and
**                                sqlite_exec() returns immediately with a
**                                return code of SQLITE_CONSTRAINT.










**
**  any              IGNORE       The record number and data is popped from
**                                the stack and there is an immediate jump
**                                to label ignoreDest.
**
**  NOT NULL         REPLACE      The NULL value is replace by the default
**                                value for that column.  If the default value
................................................................................
**                                is NULL, the action is the same as ABORT.
**
**  UNIQUE           REPLACE      The other row that conflicts with the row
**                                being inserted is removed.
**
**  CHECK            REPLACE      Illegal.  The results in an exception.
**
** The action to take is determined by the constraint itself if
** overrideError is OE_Default.  Otherwise, overrideError determines
** which action to use.

**
** The calling routine must an open read/write cursor for pTab with
** cursor number "base".  All indices of pTab must also have open
** read/write cursors with cursor number base+i for the i-th cursor.
** Except, if there is no possibility of a REPLACE action then
** cursors do not need to be open for indices where aIdxUsed[i]==0.
**
................................................................................
  int jumpInst;
  int contAddr;
  int hasTwoRecnos = (isUpdate && recnoChng);

  v = sqliteGetVdbe(pParse);
  assert( v!=0 );
  nCol = pTab->nCol;




  /* Test all NOT NULL constraints.
  */
  for(i=0; i<nCol; i++){
    if( i==pTab->iPKey ){
      /* Fix me: Make sure the INTEGER PRIMARY KEY is not NULL. */
      continue;
    }
    onError = pTab->aCol[i].notNull;
    if( onError==OE_None ) continue;
    if( overrideError!=OE_Default ){
      onError = overrideError;


    }
    if( onError==OE_Replace && pTab->aCol[i].zDflt==0 ){
      onError = OE_Abort;
    }
    sqliteVdbeAddOp(v, OP_Dup, nCol-1-i, 1);
    addr = sqliteVdbeAddOp(v, OP_NotNull, 0, 0);
    switch( onError ){

      case OE_Abort: {

        sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, 0);
        break;
      }
      case OE_Ignore: {
        sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
        break;
      }
................................................................................
  if( (recnoChng || !isUpdate) && pTab->iPKey>=0 && pTab->keyConf!=OE_Replace 
      && overrideError!=OE_Replace ){
    sqliteVdbeAddOp(v, OP_Dup, nCol, 1);
    jumpInst = sqliteVdbeAddOp(v, OP_NotExists, base, 0);
    onError = pTab->keyConf;
    if( overrideError!=OE_Default ){
      onError = overrideError;


    }
    switch( onError ){

      case OE_Abort: {

        sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, 0);
        break;
      }
      case OE_Ignore: {
        sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
        break;
      }
................................................................................
      }
    }
    sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
    onError = pIdx->onError;
    if( onError==OE_None ) continue;
    if( overrideError!=OE_Default ){
      onError = overrideError;


    }
    sqliteVdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1);
    jumpInst = sqliteVdbeAddOp(v, OP_IsUnique, base+iCur+1, 0);
    switch( onError ){

      case OE_Abort: {

        sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, 0);
        break;
      }
      case OE_Ignore: {
        assert( seenReplace==0 );
        sqliteVdbeAddOp(v, OP_Pop, nCol+extra+2+hasTwoRecnos, 0);
        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
        break;







|







 







|
<
<
<
<







 







|
<
<







 







|
|









|
|
<
<
<



|


>
>
>
>
>
>
>
>
>
>







 







|
|
|
>







 







>
>
>












>
>







>
|
>
|







 







>
>


>
|
>
|







 







>
>




>
|
>
|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
75
76
77
78
79
80
81
82




83
84
85
86
87
88
89
...
262
263
264
265
266
267
268
269


270
271
272
273
274
275
276
...
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
...
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
...
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
...
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.39 2002/01/31 15:54:22 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)
................................................................................
    goto insert_cleanup;
  }

  /* Allocate a VDBE
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto insert_cleanup;
  sqliteBeginWriteOperation(pParse);





  /* Figure out how many columns of data are supplied.  If the data
  ** is coming from a SELECT statement, then this step has to generate
  ** all the code to implement the SELECT statement and leave the data
  ** in a temporary table.  If data is coming from an expression list,
  ** then we just have to count the number of expressions.
  */
................................................................................
    sqliteVdbeResolveLabel(v, iBreak);
    sqliteVdbeAddOp(v, OP_Close, srcTab, 0);
  }
  sqliteVdbeAddOp(v, OP_Close, base, 0);
  for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
    sqliteVdbeAddOp(v, OP_Close, idx+base, 0);
  }
  sqliteEndWriteOperation(pParse);



  /*
  ** Return the number of rows inserted.
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
    sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
................................................................................
**    3.  The data in the first column of the entry after the update.
**
**    i.  Data from middle columns...
**
**    N.  The data in the last column of the entry after the update.
**
** The old recno shown as entry (1) above is omitted unless both isUpdate
** and recnoChng are 1.  isUpdate is true for UPDATEs and false for
** INSERTs and recnoChng is true if the record number is being changed.
**
** The code generated by this routine pushes additional entries onto
** the stack which are the keys for new index entries for the new record.
** The order of index keys is the same as the order of the indices on
** the pTable->pIndex list.  A key is only created for index i if 
** aIdxUsed!=0 and aIdxUsed[i]!=0.
**
** This routine also generates code to check constraints.  NOT NULL,
** CHECK, and UNIQUE constraints are all checked.  If a constraint fails,
** then the appropriate action is performed.  There are five possible
** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE.



**
**  Constraint type  Action       What Happens
**  ---------------  ----------   ----------------------------------------
**  any              ROLLBACK     The current transaction is rolled back and
**                                sqlite_exec() returns immediately with a
**                                return code of SQLITE_CONSTRAINT.
**
**  any              ABORT        Back out changes from the current command
**                                only (do not do a complete rollback) then
**                                cause sqlite_exec() to return immediately
**                                with SQLITE_CONSTRAINT.
**
**  any              FAIL         Sqlite_exec() returns immediately with a
**                                return code of SQLITE_CONSTRAINT.  The
**                                transaction is not rolled back and any
**                                prior changes are retained.
**
**  any              IGNORE       The record number and data is popped from
**                                the stack and there is an immediate jump
**                                to label ignoreDest.
**
**  NOT NULL         REPLACE      The NULL value is replace by the default
**                                value for that column.  If the default value
................................................................................
**                                is NULL, the action is the same as ABORT.
**
**  UNIQUE           REPLACE      The other row that conflicts with the row
**                                being inserted is removed.
**
**  CHECK            REPLACE      Illegal.  The results in an exception.
**
** Which action to take is determined by the overrideError parameter.
** Or if overrideError==OE_Default, then the pParse->onError parameter
** is used.  Or if pParse->onError==OE_Default then the onError value
** for the constraint is used.
**
** The calling routine must an open read/write cursor for pTab with
** cursor number "base".  All indices of pTab must also have open
** read/write cursors with cursor number base+i for the i-th cursor.
** Except, if there is no possibility of a REPLACE action then
** cursors do not need to be open for indices where aIdxUsed[i]==0.
**
................................................................................
  int jumpInst;
  int contAddr;
  int hasTwoRecnos = (isUpdate && recnoChng);

  v = sqliteGetVdbe(pParse);
  assert( v!=0 );
  nCol = pTab->nCol;
  if( overrideError==OE_Default ){
    overrideError = pParse->db->onError;
  }

  /* Test all NOT NULL constraints.
  */
  for(i=0; i<nCol; i++){
    if( i==pTab->iPKey ){
      /* Fix me: Make sure the INTEGER PRIMARY KEY is not NULL. */
      continue;
    }
    onError = pTab->aCol[i].notNull;
    if( onError==OE_None ) continue;
    if( overrideError!=OE_Default ){
      onError = overrideError;
    }else if( onError==OE_Default ){
      onError = OE_Abort;
    }
    if( onError==OE_Replace && pTab->aCol[i].zDflt==0 ){
      onError = OE_Abort;
    }
    sqliteVdbeAddOp(v, OP_Dup, nCol-1-i, 1);
    addr = sqliteVdbeAddOp(v, OP_NotNull, 0, 0);
    switch( onError ){
      case OE_Rollback:
      case OE_Abort:
      case OE_Fail: {
        sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
        break;
      }
      case OE_Ignore: {
        sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
        break;
      }
................................................................................
  if( (recnoChng || !isUpdate) && pTab->iPKey>=0 && pTab->keyConf!=OE_Replace 
      && overrideError!=OE_Replace ){
    sqliteVdbeAddOp(v, OP_Dup, nCol, 1);
    jumpInst = sqliteVdbeAddOp(v, OP_NotExists, base, 0);
    onError = pTab->keyConf;
    if( overrideError!=OE_Default ){
      onError = overrideError;
    }else if( onError==OE_Default ){
      onError = OE_Abort;
    }
    switch( onError ){
      case OE_Rollback:
      case OE_Abort:
      case OE_Fail: {
        sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
        break;
      }
      case OE_Ignore: {
        sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
        break;
      }
................................................................................
      }
    }
    sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
    onError = pIdx->onError;
    if( onError==OE_None ) continue;
    if( overrideError!=OE_Default ){
      onError = overrideError;
    }else if( onError==OE_Default ){
      onError = OE_Abort;
    }
    sqliteVdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1);
    jumpInst = sqliteVdbeAddOp(v, OP_IsUnique, base+iCur+1, 0);
    switch( onError ){
      case OE_Rollback:
      case OE_Abort:
      case OE_Fail: {
        sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
        break;
      }
      case OE_Ignore: {
        assert( seenReplace==0 );
        sqliteVdbeAddOp(v, OP_Pop, nCol+extra+2+hasTwoRecnos, 0);
        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
        break;

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
272
273
274
275
276
277
278

279
280
281
282
283
284
285
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.56 2002/01/16 21:00:27 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"

/*
** This is the callback routine for the code that initializes the
** database.  See sqliteInit() below for additional information.
................................................................................
  if( pzErrMsg ) *pzErrMsg = 0;
  if( db==0 ) goto no_mem_on_open;
  sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&db->tblDrop, SQLITE_HASH_POINTER, 0);
  sqliteHashInit(&db->idxDrop, SQLITE_HASH_POINTER, 0);
  db->nextRowid = sqliteRandomInteger();

  
  /* Open the backend database driver */
  rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe);
  if( rc!=SQLITE_OK ){
    switch( rc ){
      default: {
        sqliteSetString(pzErrMsg, "unable to open database: ", zFilename, 0);







|







 







>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.57 2002/01/31 15:54:22 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"

/*
** This is the callback routine for the code that initializes the
** database.  See sqliteInit() below for additional information.
................................................................................
  if( pzErrMsg ) *pzErrMsg = 0;
  if( db==0 ) goto no_mem_on_open;
  sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&db->tblDrop, SQLITE_HASH_POINTER, 0);
  sqliteHashInit(&db->idxDrop, SQLITE_HASH_POINTER, 0);
  db->nextRowid = sqliteRandomInteger();
  db->onError = OE_Default;
  
  /* Open the backend database driver */
  rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe);
  if( rc!=SQLITE_OK ){
    switch( rc ){
      default: {
        sqliteSetString(pzErrMsg, "unable to open database: ", zFilename, 0);

Changes to src/parse.y.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
...
102
103
104
105
106
107
108

109
110
111
112
113
114
115
...
162
163
164
165
166
167
168
169
170
171
172
173
174


175

176
177
178
179
180
181
182
183
184
...
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
...
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.44 2002/01/30 16:17:24 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  sqliteSetString(&pParse->zErrMsg,"syntax error",0);
................................................................................
ecmd ::= explain cmd.  {sqliteExec(pParse);}
ecmd ::= cmd.          {sqliteExec(pParse);}
ecmd ::= .
explain ::= EXPLAIN.    {pParse->explain = 1;}

///////////////////// Begin and end transactions. ////////////////////////////
//
cmd ::= BEGIN trans_opt.       {sqliteBeginTransaction(pParse);}
trans_opt ::= .
trans_opt ::= TRANSACTION.
trans_opt ::= TRANSACTION ids.
cmd ::= COMMIT trans_opt.      {sqliteCommitTransaction(pParse);}
cmd ::= END trans_opt.         {sqliteCommitTransaction(pParse);}
cmd ::= ROLLBACK trans_opt.    {sqliteRollbackTransaction(pParse);}

................................................................................
id(A) ::= ID(X).         {A = X;}
id(A) ::= TEMP(X).       {A = X;}
id(A) ::= OFFSET(X).     {A = X;}
id(A) ::= KEY(X).        {A = X;}
id(A) ::= ABORT(X).      {A = X;}
id(A) ::= IGNORE(X).     {A = X;}
id(A) ::= REPLACE(X).    {A = X;}

id(A) ::= CONFLICT(X).   {A = X;}

// And "ids" is an identifer-or-string.
//
%type ids {Token}
ids(A) ::= id(X).        {A = X;}
ids(A) ::= STRING(X).    {A = X;}
................................................................................
                                       {sqliteCreateIndex(pParse,0,0,X,R,0,0);}
tcons ::= CHECK expr onconf.

// The following is a non-standard extension that allows us to declare the
// default behavior when there is a constraint conflict.
//
%type onconf {int}
%type onconf_u {int}
%type confresolve {int}
onconf(A) ::= confresolve(X).                { A = X; }
onconf(A) ::= onconf_u(X).                   { A = X; }
onconf_u(A) ::= ON CONFLICT confresolve(X).  { A = X; }
onconf_u(A) ::= .                            { A = OE_Default; }


confresolve(A) ::= ABORT.                    { A = OE_Abort; }

confresolve(A) ::= IGNORE.                   { A = OE_Ignore; }
confresolve(A) ::= REPLACE.                  { A = OE_Replace; }

////////////////////////// The DROP TABLE /////////////////////////////////////
//
cmd ::= DROP TABLE ids(X).          {sqliteDropTable(pParse,&X);}

//////////////////////// The SELECT statement /////////////////////////////////
//
................................................................................
where_opt(A) ::= WHERE expr(X).       {A = X;}

%type setlist {ExprList*}
%destructor setlist {sqliteExprListDelete($$);}

////////////////////////// The UPDATE command ////////////////////////////////
//
cmd ::= UPDATE onconf_u(R) ids(X) SET setlist(Y) where_opt(Z).
    {sqliteUpdate(pParse,&X,Y,Z,R);}

setlist(A) ::= setlist(Z) COMMA ids(X) EQ expr(Y).
    {A = sqliteExprListAppend(Z,Y,&X);}
setlist(A) ::= ids(X) EQ expr(Y).   {A = sqliteExprListAppend(0,Y,&X);}

////////////////////////// The INSERT command /////////////////////////////////
//
cmd ::= INSERT onconf(R) INTO ids(X) inscollist_opt(F) VALUES LP itemlist(Y) RP.
               {sqliteInsert(pParse, &X, Y, 0, F, R);}
cmd ::= INSERT onconf(R) INTO ids(X) inscollist_opt(F) select(S).
               {sqliteInsert(pParse, &X, 0, S, F, R);}


%type itemlist {ExprList*}
%destructor itemlist {sqliteExprListDelete($$);}
%type item {Expr*}
%destructor item {sqliteExprDelete($$);}
................................................................................
//

cmd ::= DROP INDEX ids(X).      {sqliteDropIndex(pParse, &X);}


///////////////////////////// The COPY command ///////////////////////////////
//
cmd ::= COPY onconf_u(R) ids(X) FROM ids(Y) USING DELIMITERS STRING(Z).
    {sqliteCopy(pParse,&X,&Y,&Z,R);}
cmd ::= COPY onconf_u(R) ids(X) FROM ids(Y).
    {sqliteCopy(pParse,&X,&Y,0,R);}

///////////////////////////// The VACUUM command /////////////////////////////
//
cmd ::= VACUUM.                {sqliteVacuum(pParse,0);}
cmd ::= VACUUM ids(X).         {sqliteVacuum(pParse,&X);}








|







 







|







 







>







 







|
|
|
<
|
|
>
>
|
>
|
|







 







|








|

|







 







|

|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
...
163
164
165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
...
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.45 2002/01/31 15:54:22 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  sqliteSetString(&pParse->zErrMsg,"syntax error",0);
................................................................................
ecmd ::= explain cmd.  {sqliteExec(pParse);}
ecmd ::= cmd.          {sqliteExec(pParse);}
ecmd ::= .
explain ::= EXPLAIN.    {pParse->explain = 1;}

///////////////////// Begin and end transactions. ////////////////////////////
//
cmd ::= BEGIN trans_opt onconf(R).  {sqliteBeginTransaction(pParse,R);}
trans_opt ::= .
trans_opt ::= TRANSACTION.
trans_opt ::= TRANSACTION ids.
cmd ::= COMMIT trans_opt.      {sqliteCommitTransaction(pParse);}
cmd ::= END trans_opt.         {sqliteCommitTransaction(pParse);}
cmd ::= ROLLBACK trans_opt.    {sqliteRollbackTransaction(pParse);}

................................................................................
id(A) ::= ID(X).         {A = X;}
id(A) ::= TEMP(X).       {A = X;}
id(A) ::= OFFSET(X).     {A = X;}
id(A) ::= KEY(X).        {A = X;}
id(A) ::= ABORT(X).      {A = X;}
id(A) ::= IGNORE(X).     {A = X;}
id(A) ::= REPLACE(X).    {A = X;}
id(A) ::= FAIL(X).       {A = X;}
id(A) ::= CONFLICT(X).   {A = X;}

// And "ids" is an identifer-or-string.
//
%type ids {Token}
ids(A) ::= id(X).        {A = X;}
ids(A) ::= STRING(X).    {A = X;}
................................................................................
                                       {sqliteCreateIndex(pParse,0,0,X,R,0,0);}
tcons ::= CHECK expr onconf.

// The following is a non-standard extension that allows us to declare the
// default behavior when there is a constraint conflict.
//
%type onconf {int}
%type orconf {int}
%type resolvetype {int}
onconf(A) ::= .                              { A = OE_Default; }

onconf(A) ::= ON CONFLICT resolvetype(X).    { A = X; }
orconf(A) ::= .                              { A = OE_Default; }
orconf(A) ::= OR resolvetype(X).             { A = X; }
resolvetype(A) ::= ROLLBACK.                 { A = OE_Rollback; }
resolvetype(A) ::= ABORT.                    { A = OE_Abort; }
resolvetype(A) ::= FAIL.                     { A = OE_Fail; }
resolvetype(A) ::= IGNORE.                   { A = OE_Ignore; }
resolvetype(A) ::= REPLACE.                  { A = OE_Replace; }

////////////////////////// The DROP TABLE /////////////////////////////////////
//
cmd ::= DROP TABLE ids(X).          {sqliteDropTable(pParse,&X);}

//////////////////////// The SELECT statement /////////////////////////////////
//
................................................................................
where_opt(A) ::= WHERE expr(X).       {A = X;}

%type setlist {ExprList*}
%destructor setlist {sqliteExprListDelete($$);}

////////////////////////// The UPDATE command ////////////////////////////////
//
cmd ::= UPDATE orconf(R) ids(X) SET setlist(Y) where_opt(Z).
    {sqliteUpdate(pParse,&X,Y,Z,R);}

setlist(A) ::= setlist(Z) COMMA ids(X) EQ expr(Y).
    {A = sqliteExprListAppend(Z,Y,&X);}
setlist(A) ::= ids(X) EQ expr(Y).   {A = sqliteExprListAppend(0,Y,&X);}

////////////////////////// The INSERT command /////////////////////////////////
//
cmd ::= INSERT orconf(R) INTO ids(X) inscollist_opt(F) VALUES LP itemlist(Y) RP.
               {sqliteInsert(pParse, &X, Y, 0, F, R);}
cmd ::= INSERT orconf(R) INTO ids(X) inscollist_opt(F) select(S).
               {sqliteInsert(pParse, &X, 0, S, F, R);}


%type itemlist {ExprList*}
%destructor itemlist {sqliteExprListDelete($$);}
%type item {Expr*}
%destructor item {sqliteExprDelete($$);}
................................................................................
//

cmd ::= DROP INDEX ids(X).      {sqliteDropIndex(pParse, &X);}


///////////////////////////// The COPY command ///////////////////////////////
//
cmd ::= COPY orconf(R) ids(X) FROM ids(Y) USING DELIMITERS STRING(Z).
    {sqliteCopy(pParse,&X,&Y,&Z,R);}
cmd ::= COPY orconf(R) ids(X) FROM ids(Y).
    {sqliteCopy(pParse,&X,&Y,0,R);}

///////////////////////////// The VACUUM command /////////////////////////////
//
cmd ::= VACUUM.                {sqliteVacuum(pParse,0);}
cmd ::= VACUUM ids(X).         {sqliteVacuum(pParse,&X);}

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
179
180
181
182
183
184
185

186
187
188
189
190
191
192
...
233
234
235
236
237
238
239
240
241
242
243
244










245
246
247
248
249



250
251
252
253
254
255
256
257
258
259
...
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553


**    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.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.82 2002/01/30 16:17:24 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>
................................................................................
  int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
  Hash tblHash;                 /* All tables indexed by name */
  Hash idxHash;                 /* All (named) indices indexed by name */
  Hash tblDrop;                 /* Uncommitted DROP TABLEs */
  Hash idxDrop;                 /* Uncommitted DROP INDEXs */
  int lastRowid;                /* ROWID of most recent insert */
  int nextRowid;                /* Next generated rowID */

};

/*
** Possible values for the sqlite.flags.
*/
#define SQLITE_VdbeTrace      0x00000001  /* True to trace VDBE execution */
#define SQLITE_Initialized    0x00000002  /* True after initialization */
................................................................................
  u8 isCommit;     /* True if creation of this table has been committed */
  u8 isTemp;       /* True if stored in db->pBeTemp instead of db->pBe */
  u8 hasPrimKey;   /* True if there exists a primary key */
  u8 keyConf;      /* What to do in case of uniqueness conflict on iPKey */
};

/*
** SQLite supports three different ways to resolve a UNIQUE contraint
** error.  (1) It can abort the transaction return SQLITE_CONSTRAINT.
** (2) It can decide to not do the INSERT or UPDATE that was causing
** the constraint violation. (3) It can delete existing records from
** the table so that the pending INSERT or UPDATE will work without










** a constraint error.  The following there symbolic values are used
** to record which type of action to take.
*/
#define OE_None    0   /* There is no constraint to check */
#define OE_Abort   1   /* Abort and rollback. */



#define OE_Ignore  2   /* Ignore the error. Do not do the INSERT or UPDATE */
#define OE_Replace 3   /* Delete existing record, then do INSERT or UPDATE */
#define OE_Default 9   /* Do whatever the default action is */

/*
** Each SQL index is represented in memory by an
** instance of the following structure.
**
** The columns of the table that are to be indexed are described
** by the aiColumn[] field of this structure.  For example, suppose
................................................................................
int sqliteExprResolveIds(Parse*, IdList*, ExprList*, Expr*);
void sqliteExprResolveInSelect(Parse*, Expr*);
int sqliteExprAnalyzeAggregates(Parse*, Expr*);
void sqliteParseInfoReset(Parse*);
Vdbe *sqliteGetVdbe(Parse*);
int sqliteRandomByte(void);
int sqliteRandomInteger(void);
void sqliteBeginTransaction(Parse*);
void sqliteCommitTransaction(Parse*);
void sqliteRollbackTransaction(Parse*);
char *sqlite_mprintf(const char *, ...);
int sqliteExprIsConstant(Expr*);
void sqliteGenerateRowDelete(Vdbe*, Table*, int);
void sqliteGenerateRowIndexDelete(Vdbe*, Table*, int, char*);
void sqliteGenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
void sqliteCompleteInsertion(Parse*, Table*, int, char*, int, int);









|







 







>







 







|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
|
|

|
<
>
>
>
|
|
|







 







|








>
>
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
...
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259

260
261
262
263
264
265
266
267
268
269
270
271
272
...
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
**    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.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.83 2002/01/31 15:54:22 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>
................................................................................
  int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
  Hash tblHash;                 /* All tables indexed by name */
  Hash idxHash;                 /* All (named) indices indexed by name */
  Hash tblDrop;                 /* Uncommitted DROP TABLEs */
  Hash idxDrop;                 /* Uncommitted DROP INDEXs */
  int lastRowid;                /* ROWID of most recent insert */
  int nextRowid;                /* Next generated rowID */
  int onError;                  /* Default conflict algorithm */
};

/*
** Possible values for the sqlite.flags.
*/
#define SQLITE_VdbeTrace      0x00000001  /* True to trace VDBE execution */
#define SQLITE_Initialized    0x00000002  /* True after initialization */
................................................................................
  u8 isCommit;     /* True if creation of this table has been committed */
  u8 isTemp;       /* True if stored in db->pBeTemp instead of db->pBe */
  u8 hasPrimKey;   /* True if there exists a primary key */
  u8 keyConf;      /* What to do in case of uniqueness conflict on iPKey */
};

/*
** SQLite supports 4 or 5 different ways to resolve a contraint
** error.  (Only 4 are implemented as of this writing.  The fifth method
** "ABORT" is planned.)  ROLLBACK processing means that a constraint violation
** causes the operation in proces to fail and for the current transaction
** to be rolled back.  ABORT processing means the operation in process
** fails and any prior changes from that one operation are backed out,
** but the transaction is not rolled back.  FAIL processing means that
** the operation in progress stops and returns an error code.  But prior
** changes due to the same operation are not backed out and no rollback
** occurs.  IGNORE means that the particular row that caused the constraint
** error is not inserted or updated.  Processing continues and no error
** is returned.  REPLACE means that preexisting database rows that caused
** a UNIQUE constraint violation are removed so that the new insert or
** update can proceed.  Processing continues and no error is reported.
** 
** The following there symbolic values are used to record which type
** of action to take.
*/
#define OE_None     0   /* There is no constraint to check */

#define OE_Rollback 1   /* Fail the operation and rollback the transaction */
#define OE_Abort    2   /* Back out changes but do no rollback transaction */
#define OE_Fail     3   /* Stop the operation but leave all prior changes */
#define OE_Ignore   4   /* Ignore the error. Do not do the INSERT or UPDATE */
#define OE_Replace  5   /* Delete existing record, then do INSERT or UPDATE */
#define OE_Default  9   /* Do whatever the default action is */

/*
** Each SQL index is represented in memory by an
** instance of the following structure.
**
** The columns of the table that are to be indexed are described
** by the aiColumn[] field of this structure.  For example, suppose
................................................................................
int sqliteExprResolveIds(Parse*, IdList*, ExprList*, Expr*);
void sqliteExprResolveInSelect(Parse*, Expr*);
int sqliteExprAnalyzeAggregates(Parse*, Expr*);
void sqliteParseInfoReset(Parse*);
Vdbe *sqliteGetVdbe(Parse*);
int sqliteRandomByte(void);
int sqliteRandomInteger(void);
void sqliteBeginTransaction(Parse*, int);
void sqliteCommitTransaction(Parse*);
void sqliteRollbackTransaction(Parse*);
char *sqlite_mprintf(const char *, ...);
int sqliteExprIsConstant(Expr*);
void sqliteGenerateRowDelete(Vdbe*, Table*, int);
void sqliteGenerateRowIndexDelete(Vdbe*, Table*, int, char*);
void sqliteGenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
void sqliteCompleteInsertion(Parse*, Table*, int, char*, int, int);
void sqliteBeginWriteOperation(Parse*);
void sqliteEndWriteOperation(Parse*);

Changes to src/tokenize.c.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
..
58
59
60
61
62
63
64

65
66
67
68
69
70
71
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.33 2002/01/29 18:41:25 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <stdlib.h>

/*
................................................................................
  { "DELIMITERS",        0, TK_DELIMITERS,       0 },
  { "DESC",              0, TK_DESC,             0 },
  { "DISTINCT",          0, TK_DISTINCT,         0 },
  { "DROP",              0, TK_DROP,             0 },
  { "END",               0, TK_END,              0 },
  { "EXCEPT",            0, TK_EXCEPT,           0 },
  { "EXPLAIN",           0, TK_EXPLAIN,          0 },

  { "FROM",              0, TK_FROM,             0 },
  { "GLOB",              0, TK_GLOB,             0 },
  { "GROUP",             0, TK_GROUP,            0 },
  { "HAVING",            0, TK_HAVING,           0 },
  { "IGNORE",            0, TK_IGNORE,           0 },
  { "IN",                0, TK_IN,               0 },
  { "INDEX",             0, TK_INDEX,            0 },







|







 







>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
..
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.34 2002/01/31 15:54:22 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <stdlib.h>

/*
................................................................................
  { "DELIMITERS",        0, TK_DELIMITERS,       0 },
  { "DESC",              0, TK_DESC,             0 },
  { "DISTINCT",          0, TK_DISTINCT,         0 },
  { "DROP",              0, TK_DROP,             0 },
  { "END",               0, TK_END,              0 },
  { "EXCEPT",            0, TK_EXCEPT,           0 },
  { "EXPLAIN",           0, TK_EXPLAIN,          0 },
  { "FAIL",              0, TK_FAIL,             0 },
  { "FROM",              0, TK_FROM,             0 },
  { "GLOB",              0, TK_GLOB,             0 },
  { "GROUP",             0, TK_GROUP,            0 },
  { "HAVING",            0, TK_HAVING,           0 },
  { "IGNORE",            0, TK_IGNORE,           0 },
  { "IN",                0, TK_IN,               0 },
  { "INDEX",             0, TK_INDEX,            0 },

Changes to src/update.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.31 2002/01/30 16:17:24 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
*/
void sqliteUpdate(
................................................................................
    }
  }

  /* Begin generating code.
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto update_cleanup;
  if( (db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
    sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
    pParse->schemaVerified = 1;
  }

  /* Begin the database scan
  */
  pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1);
  if( pWInfo==0 ) goto update_cleanup;

  /* Remember the index of every item to be updated.
................................................................................

  /* Repeat the above with the next record to be updated, until
  ** all record selected by the WHERE clause have been updated.
  */
  sqliteVdbeAddOp(v, OP_Goto, 0, addr);
  sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
  sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
  if( (db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Commit, 0, 0);
  }

  /*
  ** Return the number of rows that were changed.
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
    sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);







|







 







|
<
<
<
<







 







|
<
<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
157
158
159
160
161
162
163
164




165
166
167
168
169
170
171
...
274
275
276
277
278
279
280
281


282
283
284
285
286
287
288
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.32 2002/01/31 15:54:22 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
*/
void sqliteUpdate(
................................................................................
    }
  }

  /* Begin generating code.
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto update_cleanup;
  sqliteBeginWriteOperation(pParse);





  /* Begin the database scan
  */
  pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1);
  if( pWInfo==0 ) goto update_cleanup;

  /* Remember the index of every item to be updated.
................................................................................

  /* Repeat the above with the next record to be updated, until
  ** all record selected by the WHERE clause have been updated.
  */
  sqliteVdbeAddOp(v, OP_Goto, 0, addr);
  sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
  sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
  sqliteEndWriteOperation(pParse);



  /*
  ** Return the number of rows that were changed.
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
    sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);

Changes to src/vdbe.c.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
....
1068
1069
1070
1071
1072
1073
1074

1075
1076
1077
1078
1079
1080
1081
....
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159






1160
1161
1162
1163
1164
1165
1166
1167

1168
1169
1170
1171
1172
1173
1174
....
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466

4467
4468
4469
4470
4471
4472
4473
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.112 2002/01/30 16:17:24 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
................................................................................
  int pc;                    /* The program counter */
  Op *pOp;                   /* Current operation */
  int rc;                    /* Value to return */
  Btree *pBt = p->pBt;       /* The backend driver */
  sqlite *db = p->db;        /* The database */
  char **zStack;             /* Text stack */
  Stack *aStack;             /* Additional stack information */

  char zBuf[100];            /* Space to sprintf() an integer */


  /* No instruction ever pushes more than a single element onto the
  ** stack.  And the stack never grows on successive executions of the
  ** same loop.  So the total number of instructions is an upper bound
  ** on the maximum stack depth required.
................................................................................
** the program.
*/
case OP_Goto: {
  pc = pOp->p2 - 1;
  break;
}

/* Opcode:  Halt P1 * *
**
** Exit immediately.  All open cursors, Lists, Sorts, etc are closed
** automatically.
**
** P1 is the result code returned by sqlite_exec().  For a normal
** halt, this should be SQLITE_OK (0).  For errors, it can be some
** other value.






**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
** every program.  So a jump past the last instruction of the program
** is the same as executing Halt.
*/
case OP_Halt: {
  if( pOp->p1!=SQLITE_OK ){
    rc = pOp->p1;

    goto abort_due_to_error;
  }else{
    pc = p->nOp-1;
  }
  break;
}

................................................................................
      fprintf(p->trace,"\n");
    }
#endif
  }

cleanup:
  Cleanup(p);
  if( rc!=SQLITE_OK ){
    closeAllCursors(p);
    sqliteBtreeRollback(pBt);
    if( db->pBeTemp ) sqliteBtreeRollback(db->pBeTemp);
    sqliteRollbackInternalChanges(db);
    db->flags &= ~SQLITE_InTrans;

  }
  return rc;

  /* Jump to here if a malloc() fails.  It's hard to get a malloc()
  ** to fail on a modern VM computer, so this code is untested.
  */
no_mem:







|







 







>







 







|






|
>
>
>
>
>
>








>







 







|





>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
....
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
....
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
....
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.113 2002/01/31 15:54:22 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
................................................................................
  int pc;                    /* The program counter */
  Op *pOp;                   /* Current operation */
  int rc;                    /* Value to return */
  Btree *pBt = p->pBt;       /* The backend driver */
  sqlite *db = p->db;        /* The database */
  char **zStack;             /* Text stack */
  Stack *aStack;             /* Additional stack information */
  int rollbackOnError = 1;   /* Do a ROLLBACK if an error is encountered */
  char zBuf[100];            /* Space to sprintf() an integer */


  /* No instruction ever pushes more than a single element onto the
  ** stack.  And the stack never grows on successive executions of the
  ** same loop.  So the total number of instructions is an upper bound
  ** on the maximum stack depth required.
................................................................................
** the program.
*/
case OP_Goto: {
  pc = pOp->p2 - 1;
  break;
}

/* Opcode:  Halt P1 P2 *
**
** Exit immediately.  All open cursors, Lists, Sorts, etc are closed
** automatically.
**
** P1 is the result code returned by sqlite_exec().  For a normal
** halt, this should be SQLITE_OK (0).  For errors, it can be some
** other value.  If P1!=0 then P2 will determine whether or not to
** rollback the current transaction.  Do not rollback if P2==OE_Fail.
** Do the rollback if P2==OE_Rollback.  If P2==OE_Abort, then back
** out all changes that have occurred during this execution of the
** VDBE, but do not rollback the transaction.  (This last case has
** not yet been implemented.  OE_Abort works like OE_Rollback for
** now.  In the future that may change.)
**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
** every program.  So a jump past the last instruction of the program
** is the same as executing Halt.
*/
case OP_Halt: {
  if( pOp->p1!=SQLITE_OK ){
    rc = pOp->p1;
    rollbackOnError = pOp->p2!=OE_Fail;
    goto abort_due_to_error;
  }else{
    pc = p->nOp-1;
  }
  break;
}

................................................................................
      fprintf(p->trace,"\n");
    }
#endif
  }

cleanup:
  Cleanup(p);
  if( rc!=SQLITE_OK && rollbackOnError ){
    closeAllCursors(p);
    sqliteBtreeRollback(pBt);
    if( db->pBeTemp ) sqliteBtreeRollback(db->pBeTemp);
    sqliteRollbackInternalChanges(db);
    db->flags &= ~SQLITE_InTrans;
    db->onError = OE_Default;
  }
  return rc;

  /* Jump to here if a malloc() fails.  It's hard to get a malloc()
  ** to fail on a modern VM computer, so this code is untested.
  */
no_mem:

Changes to test/conflict.test.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
..
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
...
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
...
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
...
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the conflict resolution extension
# to SQLite.
#
# $Id: conflict.test,v 1.3 2002/01/30 16:17:25 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table with three fields, two of which must be
# UNIQUE.
#
................................................................................
  catchsql {
    INSERT INTO t1 VALUES(1,2,4);
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}}
do_test conflict-1.3 {
  catchsql {
    INSERT ON CONFLICT IGNORE INTO t1 VALUES(1,2,4);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 3}
do_test conflict-1.4 {
  catchsql {
    INSERT ON CONFLICT REPLACE INTO t1 VALUES(1,2,4);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 4}
do_test conflict-1.5 {
  catchsql {
    INSERT ON CONFLICT ABORT INTO t1 VALUES(1,2,5);
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}}
do_test conflict-1.6 {
  catchsql {
    INSERT IGNORE INTO t1 VALUES(1,2,5);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 4}
do_test conflict-1.7 {
  catchsql {
    INSERT REPLACE INTO t1 VALUES(1,2,5);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 5}
do_test conflict-1.8 {
  catchsql {
    INSERT ON CONFLICT ABORT INTO t1 VALUES(1,2,6);
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}}

do_test conflict-1.9 {
  execsql {
    BEGIN;
................................................................................
    INSERT INTO t2 VALUES(1,3,24);
    COMMIT;
    SELECT count(*) FROM t2;
  }
} 8
do_test conflict-1.10 {
  catchsql {
    INSERT IGNORE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
    SELECT c FROM t1 ORDER BY c;
  }
} {0 {5 21}}
do_test conflict-1.11 {
  catchsql {
    INSERT REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
    SELECT c FROM t1 ORDER BY c;
  }
} {0 {14 24}}

###### Fix me!
do_test conflict-1.12 {
  catchsql {
    INSERT REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c DESC;
    SELECT c FROM t1 ORDER BY c;
  }
} {0 {14 24}}

do_test conflict-1.13 {
  execsql {
    BEGIN;
................................................................................
    INSERT INTO t1 VALUES(2,3,5);
    COMMIT;
    SELECT * FROM t1 ORDER BY c;
  }
} {1 2 3 1 3 4 2 3 5}
do_test conflict-1.14 {
  catchsql {
    UPDATE ON CONFLICT ABORT t1 SET b=3 WHERE b=2;
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}};
do_test conflict-1.15 {
  catchsql {
    UPDATE t1 SET b=3 WHERE b=2;
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}};
do_test conflict-1.16 {
  catchsql {
    UPDATE ON CONFLICT IGNORE t1 SET b=3 WHERE b=2;
    SELECT * FROM t1 ORDER BY c;
  }
} {0 {1 2 3 1 3 4 2 3 5}}
do_test conflict-1.17 {
  catchsql {
    UPDATE ON CONFLICT REPLACE t1 SET b=3 WHERE b=2;
    SELECT * FROM t1 ORDER BY c;
  }
} {0 {1 3 3 2 3 5}}

do_test conflict-2.1 {
  execsql {
    DROP TABLE t1;
................................................................................
  catchsql {
    INSERT INTO t1 VALUES(1,2,4);
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}}
do_test conflict-2.3 {
  catchsql { 
    INSERT ON CONFLICT IGNORE INTO t1 VALUES(1,2,4);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 3}
do_test conflict-2.4 {
  catchsql {
    INSERT ON CONFLICT REPLACE INTO t1 VALUES(1,2,4);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 4}
do_test conflict-2.5 {
  catchsql {
    INSERT ON CONFLICT ABORT INTO t1 VALUES(1,2,5);
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}}
do_test conflict-2.6 {
  catchsql {
    INSERT IGNORE INTO t1 VALUES(1,2,5);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 4}
do_test conflict-2.7 {
  catchsql {
    INSERT REPLACE INTO t1 VALUES(1,2,5);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 5}
do_test conflict-2.8 {
  catchsql {
    INSERT ON CONFLICT ABORT INTO t1 VALUES(1,2,6);
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}}

do_test conflict-2.9 {
  execsql {
    BEGIN;
................................................................................
    INSERT INTO t2 VALUES(2,2,24);
    COMMIT;
    SELECT count(*) FROM t2;
  }
} 8
do_test conflict-2.10 {
  catchsql {
    INSERT IGNORE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
    SELECT c FROM t1 ORDER BY c;
  }
} {0 {5 21}}
do_test conflict-2.11 {
  catchsql {
    INSERT REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
    SELECT c FROM t1 ORDER BY c;
  }
} {0 {14 24}}

###### Fix me!
do_test conflict-2.12 {
  catchsql {
    INSERT REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c DESC;
    SELECT c FROM t1 ORDER BY c;
  }
} {0 {14 24}}

do_test conflict-2.13 {
  execsql {
    BEGIN;
................................................................................
    INSERT INTO t1 VALUES(3,3,5);
    COMMIT;
    SELECT * FROM t1 ORDER BY c;
  }
} {1 2 3 2 3 4 3 3 5}
do_test conflict-2.14 {
  catchsql {
    UPDATE ON CONFLICT ABORT t1 SET a=2, b=3 WHERE b=2;
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}};
do_test conflict-2.15 {
  catchsql {
    UPDATE t1 SET a=2, b=3 WHERE b=2;
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}};
do_test conflict-2.16 {
  catchsql {
    UPDATE ON CONFLICT IGNORE t1 SET a=2, b=3 WHERE b=2;
    SELECT * FROM t1 ORDER BY c;
  }
} {0 {1 2 3 2 3 4 3 3 5}}
do_test conflict-2.17 {
  catchsql {
    UPDATE ON CONFLICT REPLACE t1 SET a=2, b=3 WHERE b=2;
    SELECT * FROM t1 ORDER BY c;
  }
} {0 {2 3 3 3 3 5}}


finish_test







|







 







|





|





|





|





|





|







 







|





|







|







 







|











|





|







 







|





|





|





|





|





|







 







|





|







|







 







|











|





|






9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
..
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
...
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
...
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
...
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the conflict resolution extension
# to SQLite.
#
# $Id: conflict.test,v 1.4 2002/01/31 15:54:23 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table with three fields, two of which must be
# UNIQUE.
#
................................................................................
  catchsql {
    INSERT INTO t1 VALUES(1,2,4);
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}}
do_test conflict-1.3 {
  catchsql {
    INSERT OR IGNORE INTO t1 VALUES(1,2,4);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 3}
do_test conflict-1.4 {
  catchsql {
    INSERT OR REPLACE INTO t1 VALUES(1,2,4);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 4}
do_test conflict-1.5 {
  catchsql {
    INSERT OR ABORT INTO t1 VALUES(1,2,5);
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}}
do_test conflict-1.6 {
  catchsql {
    INSERT OR IGNORE INTO t1 VALUES(1,2,5);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 4}
do_test conflict-1.7 {
  catchsql {
    INSERT OR REPLACE INTO t1 VALUES(1,2,5);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 5}
do_test conflict-1.8 {
  catchsql {
    INSERT OR ABORT INTO t1 VALUES(1,2,6);
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}}

do_test conflict-1.9 {
  execsql {
    BEGIN;
................................................................................
    INSERT INTO t2 VALUES(1,3,24);
    COMMIT;
    SELECT count(*) FROM t2;
  }
} 8
do_test conflict-1.10 {
  catchsql {
    INSERT OR IGNORE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
    SELECT c FROM t1 ORDER BY c;
  }
} {0 {5 21}}
do_test conflict-1.11 {
  catchsql {
    INSERT OR REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
    SELECT c FROM t1 ORDER BY c;
  }
} {0 {14 24}}

###### Fix me!
do_test conflict-1.12 {
  catchsql {
    INSERT OR REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c DESC;
    SELECT c FROM t1 ORDER BY c;
  }
} {0 {14 24}}

do_test conflict-1.13 {
  execsql {
    BEGIN;
................................................................................
    INSERT INTO t1 VALUES(2,3,5);
    COMMIT;
    SELECT * FROM t1 ORDER BY c;
  }
} {1 2 3 1 3 4 2 3 5}
do_test conflict-1.14 {
  catchsql {
    UPDATE OR ABORT t1 SET b=3 WHERE b=2;
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}};
do_test conflict-1.15 {
  catchsql {
    UPDATE t1 SET b=3 WHERE b=2;
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}};
do_test conflict-1.16 {
  catchsql {
    UPDATE OR IGNORE t1 SET b=3 WHERE b=2;
    SELECT * FROM t1 ORDER BY c;
  }
} {0 {1 2 3 1 3 4 2 3 5}}
do_test conflict-1.17 {
  catchsql {
    UPDATE OR REPLACE t1 SET b=3 WHERE b=2;
    SELECT * FROM t1 ORDER BY c;
  }
} {0 {1 3 3 2 3 5}}

do_test conflict-2.1 {
  execsql {
    DROP TABLE t1;
................................................................................
  catchsql {
    INSERT INTO t1 VALUES(1,2,4);
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}}
do_test conflict-2.3 {
  catchsql { 
    INSERT OR IGNORE INTO t1 VALUES(1,2,4);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 3}
do_test conflict-2.4 {
  catchsql {
    INSERT OR REPLACE INTO t1 VALUES(1,2,4);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 4}
do_test conflict-2.5 {
  catchsql {
    INSERT OR ABORT INTO t1 VALUES(1,2,5);
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}}
do_test conflict-2.6 {
  catchsql {
    INSERT OR IGNORE INTO t1 VALUES(1,2,5);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 4}
do_test conflict-2.7 {
  catchsql {
    INSERT OR REPLACE INTO t1 VALUES(1,2,5);
    SELECT c FROM t1 ORDER BY c;
  }
} {0 5}
do_test conflict-2.8 {
  catchsql {
    INSERT OR ABORT INTO t1 VALUES(1,2,6);
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}}

do_test conflict-2.9 {
  execsql {
    BEGIN;
................................................................................
    INSERT INTO t2 VALUES(2,2,24);
    COMMIT;
    SELECT count(*) FROM t2;
  }
} 8
do_test conflict-2.10 {
  catchsql {
    INSERT OR IGNORE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
    SELECT c FROM t1 ORDER BY c;
  }
} {0 {5 21}}
do_test conflict-2.11 {
  catchsql {
    INSERT OR REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
    SELECT c FROM t1 ORDER BY c;
  }
} {0 {14 24}}

###### Fix me!
do_test conflict-2.12 {
  catchsql {
    INSERT OR REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c DESC;
    SELECT c FROM t1 ORDER BY c;
  }
} {0 {14 24}}

do_test conflict-2.13 {
  execsql {
    BEGIN;
................................................................................
    INSERT INTO t1 VALUES(3,3,5);
    COMMIT;
    SELECT * FROM t1 ORDER BY c;
  }
} {1 2 3 2 3 4 3 3 5}
do_test conflict-2.14 {
  catchsql {
    UPDATE OR ABORT t1 SET a=2, b=3 WHERE b=2;
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}};
do_test conflict-2.15 {
  catchsql {
    UPDATE t1 SET a=2, b=3 WHERE b=2;
    SELECT c FROM t1 ORDER BY c;
  }
} {1 {constraint failed}};
do_test conflict-2.16 {
  catchsql {
    UPDATE OR IGNORE t1 SET a=2, b=3 WHERE b=2;
    SELECT * FROM t1 ORDER BY c;
  }
} {0 {1 2 3 2 3 4 3 3 5}}
do_test conflict-2.17 {
  catchsql {
    UPDATE OR REPLACE t1 SET a=2, b=3 WHERE b=2;
    SELECT * FROM t1 ORDER BY c;
  }
} {0 {2 3 3 3 3 5}}


finish_test

Changes to test/copy.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the COPY statement.
#
# $Id: copy.test,v 1.7 2002/01/30 16:17:25 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a file of data from which to copy.
#
set f [open data1.txt w]
................................................................................
  }
} {1 {constraint failed}}
do_test copy-5.3 {
  set fd [open data6.txt w]
  puts $fd "33|22|44"
  close $fd
  catchsql {
    COPY ON CONFLICT IGNORE t1 FROM 'data6.txt' USING DELIMITERS '|';
    SELECT * FROM t1;
  }
} {0 {11 22 33 22 33 11}}
do_test copy-5.4 {
  set fd [open data6.txt w]
  puts $fd "33|22|44"
  close $fd
  catchsql {
    COPY ON CONFLICT REPLACE t1 FROM 'data6.txt' USING DELIMITERS '|';
    SELECT * FROM t1;
  }
} {0 {22 33 11 33 22 44}}
 

# Cleanup 
#
file delete -force data1.txt data2.txt data3.txt data4.txt data5.txt data6.txt

finish_test







|







 







|








|










7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the COPY statement.
#
# $Id: copy.test,v 1.8 2002/01/31 15:54:23 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a file of data from which to copy.
#
set f [open data1.txt w]
................................................................................
  }
} {1 {constraint failed}}
do_test copy-5.3 {
  set fd [open data6.txt w]
  puts $fd "33|22|44"
  close $fd
  catchsql {
    COPY OR IGNORE t1 FROM 'data6.txt' USING DELIMITERS '|';
    SELECT * FROM t1;
  }
} {0 {11 22 33 22 33 11}}
do_test copy-5.4 {
  set fd [open data6.txt w]
  puts $fd "33|22|44"
  close $fd
  catchsql {
    COPY OR REPLACE t1 FROM 'data6.txt' USING DELIMITERS '|';
    SELECT * FROM t1;
  }
} {0 {22 33 11 33 22 44}}
 

# Cleanup 
#
file delete -force data1.txt data2.txt data3.txt data4.txt data5.txt data6.txt

finish_test

Changes to test/notnull.test.

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
..
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
...
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
...
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
...
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
...
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the NOT NULL constraint.
#
# $Id: notnull.test,v 1.1 2002/01/30 04:32:01 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test notnull-1.0 {
  execsql {
    CREATE TABLE t1 (
      a NOT NULL,
      b NOT NULL DEFAULT 5,
      c NOT NULL REPLACE DEFAULT 6,
      d NOT NULL IGNORE DEFAULT 7,
      e NOT NULL ABORT DEFAULT 8
    );
    SELECT * FROM t1;
  }
} {}
do_test notnull-1.1 {
  catchsql {
    DELETE FROM t1;
................................................................................
    INSERT INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-1.3 {
  catchsql {
    DELETE FROM t1;
    INSERT IGNORE INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-1.4 {
  catchsql {
    DELETE FROM t1;
    INSERT REPLACE INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-1.5 {
  catchsql {
    DELETE FROM t1;
    INSERT ABORT INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-1.6 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.7 {
  catchsql {
    DELETE FROM t1;
    INSERT IGNORE INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.8 {
  catchsql {
    DELETE FROM t1;
    INSERT REPLACE INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.9 {
  catchsql {
    DELETE FROM t1;
    INSERT ABORT INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.10 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-1.11 {
  catchsql {
    DELETE FROM t1;
    INSERT IGNORE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-1.12 {
  catchsql {
    DELETE FROM t1;
    INSERT REPLACE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.13 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 6 4 5}}
do_test notnull-1.14 {
  catchsql {
    DELETE FROM t1;
    INSERT IGNORE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-1.15 {
  catchsql {
    DELETE FROM t1;
    INSERT REPLACE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 6 4 5}}
do_test notnull-1.16 {
  catchsql {
    DELETE FROM t1;
    INSERT ABORT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-1.17 {
  catchsql {
    DELETE FROM t1;
    INSERT ABORT INTO t1(a,b,c,d,e) VALUES(1,2,3,null,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-1.18 {
  catchsql {
    DELETE FROM t1;
    INSERT ABORT INTO t1(a,b,c,e) VALUES(1,2,3,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 3 7 5}}
do_test notnull-1.19 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d) VALUES(1,2,3,4);
................................................................................
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,null);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-1.21 {
  catchsql {
    DELETE FROM t1;
    INSERT REPLACE INTO t1(e,d,c,b,a) VALUES(1,2,3,null,5);
    SELECT * FROM t1 order by a;
  }
} {0 {5 5 3 2 1}}

do_test notnull-2.1 {
  catchsql {
    DELETE FROM t1;
................................................................................
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-2.2 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE ON CONFLICT REPLACE t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-2.3 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE ON CONFLICT IGNORE t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-2.4 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE ON CONFLICT ABORT t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-2.5 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
................................................................................
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-2.6 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE ON CONFLICT REPLACE t1 SET b=null, d=e, e=d;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 5 3 5 4}}
do_test notnull-2.7 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE ON CONFLICT IGNORE t1 SET b=null, d=e, e=d;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-2.8 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
................................................................................
    INSERT INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-3.3 {
  catchsql {
    DELETE FROM t1;
    INSERT IGNORE INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-3.4 {
  catchsql {
    DELETE FROM t1;
    INSERT REPLACE INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-3.5 {
  catchsql {
    DELETE FROM t1;
    INSERT ABORT INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-3.6 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.7 {
  catchsql {
    DELETE FROM t1;
    INSERT IGNORE INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.8 {
  catchsql {
    DELETE FROM t1;
    INSERT REPLACE INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.9 {
  catchsql {
    DELETE FROM t1;
    INSERT ABORT INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.10 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-3.11 {
  catchsql {
    DELETE FROM t1;
    INSERT IGNORE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-3.12 {
  catchsql {
    DELETE FROM t1;
    INSERT REPLACE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.13 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 6 4 5}}
do_test notnull-3.14 {
  catchsql {
    DELETE FROM t1;
    INSERT IGNORE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-3.15 {
  catchsql {
    DELETE FROM t1;
    INSERT REPLACE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 6 4 5}}
do_test notnull-3.16 {
  catchsql {
    DELETE FROM t1;
    INSERT ABORT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-3.17 {
  catchsql {
    DELETE FROM t1;
    INSERT ABORT INTO t1(a,b,c,d,e) VALUES(1,2,3,null,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-3.18 {
  catchsql {
    DELETE FROM t1;
    INSERT ABORT INTO t1(a,b,c,e) VALUES(1,2,3,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 3 7 5}}
do_test notnull-3.19 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d) VALUES(1,2,3,4);
................................................................................
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,null);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-3.21 {
  catchsql {
    DELETE FROM t1;
    INSERT REPLACE INTO t1(e,d,c,b,a) VALUES(1,2,3,null,5);
    SELECT * FROM t1 order by a;
  }
} {0 {5 5 3 2 1}}

do_test notnull-4.1 {
  catchsql {
    DELETE FROM t1;
................................................................................
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-4.2 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE ON CONFLICT REPLACE t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-4.3 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE ON CONFLICT IGNORE t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-4.4 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE ON CONFLICT ABORT t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-4.5 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
................................................................................
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-4.6 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE ON CONFLICT REPLACE t1 SET b=null, d=e, e=d;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 5 3 5 4}}
do_test notnull-4.7 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE ON CONFLICT IGNORE t1 SET b=null, d=e, e=d;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-4.8 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);







|









|
|
|







 







|






|






|













|






|






|













|






|













|






|






|






|






|







 







|







 







|







|







|







 







|







|







 







|






|






|













|






|






|













|






|













|






|






|






|






|







 







|







 







|







|







|







 







|







|







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
..
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
...
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
...
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
...
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
...
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the NOT NULL constraint.
#
# $Id: notnull.test,v 1.2 2002/01/31 15:54:23 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test notnull-1.0 {
  execsql {
    CREATE TABLE t1 (
      a NOT NULL,
      b NOT NULL DEFAULT 5,
      c NOT NULL ON CONFLICT REPLACE DEFAULT 6,
      d NOT NULL ON CONFLICT IGNORE DEFAULT 7,
      e NOT NULL ON CONFLICT ABORT DEFAULT 8
    );
    SELECT * FROM t1;
  }
} {}
do_test notnull-1.1 {
  catchsql {
    DELETE FROM t1;
................................................................................
    INSERT INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-1.3 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-1.4 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-1.5 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-1.6 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.7 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.8 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.9 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.10 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-1.11 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-1.12 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.13 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 6 4 5}}
do_test notnull-1.14 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-1.15 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 6 4 5}}
do_test notnull-1.16 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-1.17 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,3,null,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-1.18 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,b,c,e) VALUES(1,2,3,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 3 7 5}}
do_test notnull-1.19 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d) VALUES(1,2,3,4);
................................................................................
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,null);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-1.21 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(e,d,c,b,a) VALUES(1,2,3,null,5);
    SELECT * FROM t1 order by a;
  }
} {0 {5 5 3 2 1}}

do_test notnull-2.1 {
  catchsql {
    DELETE FROM t1;
................................................................................
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-2.2 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR REPLACE t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-2.3 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR IGNORE t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-2.4 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR ABORT t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-2.5 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
................................................................................
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-2.6 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR REPLACE t1 SET b=null, d=e, e=d;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 5 3 5 4}}
do_test notnull-2.7 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR IGNORE t1 SET b=null, d=e, e=d;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-2.8 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
................................................................................
    INSERT INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-3.3 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-3.4 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-3.5 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-3.6 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.7 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.8 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.9 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.10 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-3.11 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-3.12 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.13 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 6 4 5}}
do_test notnull-3.14 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-3.15 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 6 4 5}}
do_test notnull-3.16 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-3.17 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,3,null,5);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-3.18 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,b,c,e) VALUES(1,2,3,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 3 7 5}}
do_test notnull-3.19 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d) VALUES(1,2,3,4);
................................................................................
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,null);
    SELECT * FROM t1 order by a;
  }
} {1 {constraint failed}}
do_test notnull-3.21 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(e,d,c,b,a) VALUES(1,2,3,null,5);
    SELECT * FROM t1 order by a;
  }
} {0 {5 5 3 2 1}}

do_test notnull-4.1 {
  catchsql {
    DELETE FROM t1;
................................................................................
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-4.2 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR REPLACE t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-4.3 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR IGNORE t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-4.4 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR ABORT t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-4.5 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
................................................................................
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {constraint failed}}
do_test notnull-4.6 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR REPLACE t1 SET b=null, d=e, e=d;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 5 3 5 4}}
do_test notnull-4.7 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR IGNORE t1 SET b=null, d=e, e=d;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-4.8 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);

Changes to www/download.tcl.

1
2
3
4
5
6
7
8
9
10
11
..
36
37
38
39
40
41
42





43
44
45
46
47
48
49
50
51
52
53
54



55

56








57
58
59
60
61
62
63
#
# Run this TCL script to generate HTML for the download.html file.
#
set rcsid {$Id: download.tcl,v 1.2 2001/11/24 13:23:05 drh Exp $}

puts {<html>
<head><title>SQLite Download Page</title></head>
<body bgcolor=white>
<h1 align=center>SQLite Download Page</h1>}
#<p align=center>}
#puts "This page was last modified on [lrange $rcsid 3 4] UTC<br>"
................................................................................
}

Product tclsqlite.so.gz {
  Bindings for TCL.  You can import this shared library into either
  tclsh or wish to get SQLite database access from Tcl/Tk.
  See <a href="tclsqlite.html">the documentation</a> for details.
}






puts {<h2>Precompiled Binaries For Windows</h2>}

Product sqlite.zip {
  A command-line program for accessing and modifing SQLite databases.
  See <a href="sqlite.html">the documentation</a> for additional information.
}
Product tclsqlite.zip {
  Bindings for TCL.  You can import this shared library into either
  tclsh or wish to get SQLite database access from Tcl/Tk.
  See <a href="tclsqlite.html">the documentation</a> for details.
}





puts {<h2>Source Code</h2>}









foreach name [lsort -dict -decreasing [glob -nocomplain sqlite-*.tar.gz]] {
  regexp {sqlite-(.*)\.tar\.gz} $name match vers
  Product $name "
      Version $vers of the source tree including all documentation.
  "
}



|







 







>
>
>
>
>












>
>
>
|
>

>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
..
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#
# Run this TCL script to generate HTML for the download.html file.
#
set rcsid {$Id: download.tcl,v 1.3 2002/01/31 15:54:23 drh Exp $}

puts {<html>
<head><title>SQLite Download Page</title></head>
<body bgcolor=white>
<h1 align=center>SQLite Download Page</h1>}
#<p align=center>}
#puts "This page was last modified on [lrange $rcsid 3 4] UTC<br>"
................................................................................
}

Product tclsqlite.so.gz {
  Bindings for TCL.  You can import this shared library into either
  tclsh or wish to get SQLite database access from Tcl/Tk.
  See <a href="tclsqlite.html">the documentation</a> for details.
}

Product sqlite.so.gz {
  A precompiled shared-library for Linux.  This is the same as
  <b>tclsqlite.so.gz</b> but without the TCL bindings.
}

puts {<h2>Precompiled Binaries For Windows</h2>}

Product sqlite.zip {
  A command-line program for accessing and modifing SQLite databases.
  See <a href="sqlite.html">the documentation</a> for additional information.
}
Product tclsqlite.zip {
  Bindings for TCL.  You can import this shared library into either
  tclsh or wish to get SQLite database access from Tcl/Tk.
  See <a href="tclsqlite.html">the documentation</a> for details.
}
Product sqlitedll.zip {
  This is a DLL of the SQLite library without the TCL bindings.
  The only external dependency is MSVCRT.DLL.
}

puts {<h2>Source Code</h2>}

Product {sqlite_source.zip} {
  This ZIP archive contains pure C source code for the SQLite library.
  Unlike the tarballs below, all of the preprocessing has already been
  done on these C source code, so you can just hand the files directly to
  your favorite C compiler.  This file is provided as a service to
  MS-Windows users who lack the build support infrastructure of Unix.
}

foreach name [lsort -dict -decreasing [glob -nocomplain sqlite-*.tar.gz]] {
  regexp {sqlite-(.*)\.tar\.gz} $name match vers
  Product $name "
      Version $vers of the source tree including all documentation.
  "
}

Changes to www/lang.tcl.

1
2
3
4
5
6
7
8
9
10
11
...
328
329
330
331
332
333
334





335
336
337
338
339
340
341
#
# Run this Tcl script to generate the sqlite.html file.
#
set rcsid {$Id: lang.tcl,v 1.19 2002/01/30 16:17:25 drh Exp $}

puts {<html>
<head>
  <title>Query Language Understood By SQLite</title>
</head>
<body bgcolor=white>
<h1 align=center>
................................................................................
The default is abort ABORT.  Different constraints within the same
table may have different default conflict resolution algorithms.
If an COPY, INSERT, or UPDATE command specifies a different conflict
resolution algorithm, then that algorithm is used in place of the
default algorithm specified in the CREATE TABLE statement.
See the section titled
<a href="#conflict">ON CONFLICT</a> for additional information.</p>






<p>There are no arbitrary limits on the number
of columns or on the number of constraints in a table.
The total amount of data in a single row is limited to about
1 megabytes.  (This limit can be increased to 16MB by changing
a single #define in the source code and recompiling.)</p>




|







 







>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
...
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
#
# Run this Tcl script to generate the sqlite.html file.
#
set rcsid {$Id: lang.tcl,v 1.20 2002/01/31 15:54:23 drh Exp $}

puts {<html>
<head>
  <title>Query Language Understood By SQLite</title>
</head>
<body bgcolor=white>
<h1 align=center>
................................................................................
The default is abort ABORT.  Different constraints within the same
table may have different default conflict resolution algorithms.
If an COPY, INSERT, or UPDATE command specifies a different conflict
resolution algorithm, then that algorithm is used in place of the
default algorithm specified in the CREATE TABLE statement.
See the section titled
<a href="#conflict">ON CONFLICT</a> for additional information.</p>

<p>CHECK constraints are ignored in the current implementation.
Support for CHECK constraints may be added in the future.  As of
version 2.3.0, NOT NULL, PRIMARY KEY, and UNIQUE constraints all
work.</p>

<p>There are no arbitrary limits on the number
of columns or on the number of constraints in a table.
The total amount of data in a single row is limited to about
1 megabytes.  (This limit can be increased to 16MB by changing
a single #define in the source code and recompiling.)</p>