/ Check-in [3e8889d7]
Login

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

Overview
Comment:Additional testing of the ATTACH command with bug fixes for the new problems that the tests found. (CVS 998)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 3e8889d7ce5e99fc855526fc1bb62ddbe282bfc5
User & Date: drh 2003-06-03 01:47:11
Context
2003-06-04
12:23
Avoid corrupting indices when doing a REPLACE on a table with an INTEGER PRIMARY KEY that also has another index. Ticket #334. (CVS 999) check-in: e813faae user: drh tags: trunk
2003-06-03
01:47
Additional testing of the ATTACH command with bug fixes for the new problems that the tests found. (CVS 998) check-in: 3e8889d7 user: drh tags: trunk
2003-06-02
23:14
The OP_Checkpoint opcode is now a no-op if invoked on a database that already has an active checkpoint journal. Ticket #333. (CVS 997) check-in: daf7b940 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/attach.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
144
145
146
147
148
149
150

151
152
153
154
155
156
157
...
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
**    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.
**
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c,v 1.4 2003/05/31 16:21:12 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is called by the parser to process an ATTACH statement:
**
**     ATTACH DATABASE filename AS dbname
................................................................................
  const Token *pName  /* Name of the view, trigger, or index */
){
  sqlite *db;

  if( iDb<0 || iDb==1 ) return 0;
  db = pParse->db;
  assert( db->nDb>iDb );

  pFix->zDb = db->aDb[iDb].zName;
  pFix->zType = zType;
  pFix->pName = pName;
  return 1;
}

/*
................................................................................
  if( pList==0 ) return 0;
  zDb = pFix->zDb;
  for(i=0; i<pList->nSrc; i++){
    if( pList->a[i].zDatabase==0 ){
      pList->a[i].zDatabase = sqliteStrDup(zDb);
    }else if( sqliteStrICmp(pList->a[i].zDatabase,zDb)!=0 ){
      sqliteErrorMsg(pFix->pParse,
         "%s %.*s cannot reference objects in database %s",

         pFix->zType, pFix->pName->n, pFix->pName->z, pList->a[i].zDatabase);
      return 1;
    }
    if( sqliteFixSelect(pFix, pList->a[i].pSelect) ) return 1;
    if( sqliteFixExpr(pFix, pList->a[i].pOn) ) return 1;
  }
  return 0;
}







|







 







>







 







|
>
|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
**    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.
**
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c,v 1.5 2003/06/03 01:47:11 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is called by the parser to process an ATTACH statement:
**
**     ATTACH DATABASE filename AS dbname
................................................................................
  const Token *pName  /* Name of the view, trigger, or index */
){
  sqlite *db;

  if( iDb<0 || iDb==1 ) return 0;
  db = pParse->db;
  assert( db->nDb>iDb );
  pFix->pParse = pParse;
  pFix->zDb = db->aDb[iDb].zName;
  pFix->zType = zType;
  pFix->pName = pName;
  return 1;
}

/*
................................................................................
  if( pList==0 ) return 0;
  zDb = pFix->zDb;
  for(i=0; i<pList->nSrc; i++){
    if( pList->a[i].zDatabase==0 ){
      pList->a[i].zDatabase = sqliteStrDup(zDb);
    }else if( sqliteStrICmp(pList->a[i].zDatabase,zDb)!=0 ){
      sqliteErrorMsg(pFix->pParse,
         "%s %z cannot reference objects in database %s",
         pFix->zType, sqliteStrNDup(pFix->pName->z, pFix->pName->n),
         pList->a[i].zDatabase);
      return 1;
    }
    if( sqliteFixSelect(pFix, pList->a[i].pSelect) ) return 1;
    if( sqliteFixExpr(pFix, pList->a[i].pOn) ) return 1;
  }
  return 0;
}

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
**    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.190 2003/06/02 23:14:13 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
................................................................................
  u8 iTabDb;              /* Database containing Trigger.table              */
  u8 op;                  /* One of TK_DELETE, TK_UPDATE, TK_INSERT         */
  u8 tr_tm;               /* One of TK_BEFORE, TK_AFTER */
  Expr *pWhen;            /* The WHEN clause of the expresion (may be NULL) */
  IdList *pColumns;       /* If this is an UPDATE OF <column-list> trigger,
                             the <column-list> is stored here */
  int foreach;            /* One of TK_ROW or TK_STATEMENT */
  Token *pNameToken;      /* Token containing zName. Use during parsing only */

  TriggerStep *step_list; /* Link list of trigger program steps             */
  Trigger *pNext;         /* Next trigger associated with the table */
};

/*
 * An instance of struct TriggerStep is used to store a single SQL statement







|







 







|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
**    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.191 2003/06/03 01:47:11 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
................................................................................
  u8 iTabDb;              /* Database containing Trigger.table              */
  u8 op;                  /* One of TK_DELETE, TK_UPDATE, TK_INSERT         */
  u8 tr_tm;               /* One of TK_BEFORE, TK_AFTER */
  Expr *pWhen;            /* The WHEN clause of the expresion (may be NULL) */
  IdList *pColumns;       /* If this is an UPDATE OF <column-list> trigger,
                             the <column-list> is stored here */
  int foreach;            /* One of TK_ROW or TK_STATEMENT */
  Token nameToken;        /* Token containing zName. Use during parsing only */

  TriggerStep *step_list; /* Link list of trigger program steps             */
  Trigger *pNext;         /* Next trigger associated with the table */
};

/*
 * An instance of struct TriggerStep is used to store a single SQL statement

Changes to src/trigger.c.

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
...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
...
362
363
364
365
366
367
368

369
370
371
372
373
374
375
  int isTemp          /* True if the TEMPORARY keyword is present */
){
  Trigger *nt;
  Table   *tab;
  char *zName = 0;        /* Name of the trigger */
  sqlite *db = pParse->db;
  int iDb;                /* When database to store the trigger in */


  /* Check that: 
  ** 1. the trigger name does not already exist.
  ** 2. the table (or view) does exist in the same database as the trigger.
  ** 3. that we are not trying to create a trigger on the sqlite_master table
  ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
  ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
  */
  if( sqlite_malloc_failed ) goto trigger_cleanup;
  assert( pTableName->nSrc==1 );
  assert( pTableName->a[0].zDatabase==0 );
  if( pParse->initFlag ){

    pTableName->a[0].zDatabase = db->aDb[pParse->iDb].zName;


  }
  tab = sqliteSrcListLookup(pParse, pTableName);
  pTableName->a[0].zDatabase = 0;
  if( !tab ){
    goto trigger_cleanup;
  }
  iDb = isTemp ? 1 : tab->iDb;
  if( iDb>=2 && !pParse->initFlag ){
    sqliteErrorMsg(pParse, "triggers may not be added to auxiliary "
       "database %s", db->aDb[tab->iDb].zName);
................................................................................
  nt->iDb = iDb;
  nt->iTabDb = tab->iDb;
  nt->op = op;
  nt->tr_tm = tr_tm;
  nt->pWhen = sqliteExprDup(pWhen);
  nt->pColumns = sqliteIdListDup(pColumns);
  nt->foreach = foreach;
  nt->pNameToken = pName;
  assert( pParse->pNewTrigger==0 );
  pParse->pNewTrigger = nt;

trigger_cleanup:
  sqliteFree(zName);
  sqliteSrcListDelete(pTableName);
  sqliteIdListDelete(pColumns);
................................................................................
  nt = pParse->pNewTrigger;
  pParse->pNewTrigger = 0;
  nt->step_list = pStepList;
  while( pStepList ){
    pStepList->pTrig = nt;
    pStepList = pStepList->pNext;
  }
  if( sqliteFixInit(&sFix, pParse, nt->iDb, "trigger", nt->pNameToken) 
          && sqliteFixTriggerStep(&sFix, nt->step_list) ){
    goto triggerfinish_cleanup;
  }
  nt->pNameToken = 0;

  /* if we are not initializing, and this trigger is not on a TEMP table, 
  ** build the sqlite_master entry
  */
  if( !pParse->initFlag ){
    static VdbeOp insertTrig[] = {
      { OP_NewRecno,   0, 0,  0          },
................................................................................
void sqliteDeleteTrigger(Trigger *pTrigger){
  if( pTrigger==0 ) return;
  sqliteDeleteTriggerStep(pTrigger->step_list);
  sqliteFree(pTrigger->name);
  sqliteFree(pTrigger->table);
  sqliteExprDelete(pTrigger->pWhen);
  sqliteIdListDelete(pTrigger->pColumns);

  sqliteFree(pTrigger);
}

/*
 * This function is called to drop a trigger from the database schema. 
 *
 * This may be called directly from the parser and therefore identifies







>










<
|
>
|
>
>


<







 







|







 







|



<







 







>







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
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
168
169
170
171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
...
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
  int isTemp          /* True if the TEMPORARY keyword is present */
){
  Trigger *nt;
  Table   *tab;
  char *zName = 0;        /* Name of the trigger */
  sqlite *db = pParse->db;
  int iDb;                /* When database to store the trigger in */
  DbFixer sFix;

  /* Check that: 
  ** 1. the trigger name does not already exist.
  ** 2. the table (or view) does exist in the same database as the trigger.
  ** 3. that we are not trying to create a trigger on the sqlite_master table
  ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
  ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
  */
  if( sqlite_malloc_failed ) goto trigger_cleanup;
  assert( pTableName->nSrc==1 );

  if( pParse->initFlag 
   && sqliteFixInit(&sFix, pParse, pParse->iDb, "trigger", pName)
   && sqliteFixSrcList(&sFix, pTableName)
  ){
    goto trigger_cleanup;
  }
  tab = sqliteSrcListLookup(pParse, pTableName);

  if( !tab ){
    goto trigger_cleanup;
  }
  iDb = isTemp ? 1 : tab->iDb;
  if( iDb>=2 && !pParse->initFlag ){
    sqliteErrorMsg(pParse, "triggers may not be added to auxiliary "
       "database %s", db->aDb[tab->iDb].zName);
................................................................................
  nt->iDb = iDb;
  nt->iTabDb = tab->iDb;
  nt->op = op;
  nt->tr_tm = tr_tm;
  nt->pWhen = sqliteExprDup(pWhen);
  nt->pColumns = sqliteIdListDup(pColumns);
  nt->foreach = foreach;
  sqliteTokenCopy(&nt->nameToken,pName);
  assert( pParse->pNewTrigger==0 );
  pParse->pNewTrigger = nt;

trigger_cleanup:
  sqliteFree(zName);
  sqliteSrcListDelete(pTableName);
  sqliteIdListDelete(pColumns);
................................................................................
  nt = pParse->pNewTrigger;
  pParse->pNewTrigger = 0;
  nt->step_list = pStepList;
  while( pStepList ){
    pStepList->pTrig = nt;
    pStepList = pStepList->pNext;
  }
  if( sqliteFixInit(&sFix, pParse, nt->iDb, "trigger", &nt->nameToken) 
          && sqliteFixTriggerStep(&sFix, nt->step_list) ){
    goto triggerfinish_cleanup;
  }


  /* if we are not initializing, and this trigger is not on a TEMP table, 
  ** build the sqlite_master entry
  */
  if( !pParse->initFlag ){
    static VdbeOp insertTrig[] = {
      { OP_NewRecno,   0, 0,  0          },
................................................................................
void sqliteDeleteTrigger(Trigger *pTrigger){
  if( pTrigger==0 ) return;
  sqliteDeleteTriggerStep(pTrigger->step_list);
  sqliteFree(pTrigger->name);
  sqliteFree(pTrigger->table);
  sqliteExprDelete(pTrigger->pWhen);
  sqliteIdListDelete(pTrigger->pColumns);
  if( pTrigger->nameToken.dyn ) sqliteFree((char*)pTrigger->nameToken.z);
  sqliteFree(pTrigger);
}

/*
 * This function is called to drop a trigger from the database schema. 
 *
 * This may be called directly from the parser and therefore identifies

Changes to test/attach.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
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.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: attach.test,v 1.6 2003/05/31 16:21:13 drh Exp $
#

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

for {set i 2} {$i<=15} {incr i} {
  file delete -force test$i.db
................................................................................
} {102 910 607 1314}
do_test attach-4.13 {
  execsql {
    SELECT * FROM main.v3;
  }
} {910 1112 1516}







































































































for {set i 2} {$i<=15} {incr i} {
  catch {db$i close}
}



finish_test







|







 







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



>



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: attach.test,v 1.7 2003/06/03 01:47:12 drh Exp $
#

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

for {set i 2} {$i<=15} {incr i} {
  file delete -force test$i.db
................................................................................
} {102 910 607 1314}
do_test attach-4.13 {
  execsql {
    SELECT * FROM main.v3;
  }
} {910 1112 1516}

# Tests for the sqliteFix...() routines in attach.c
#
do_test attach-5.1 {
  db close
  sqlite db test.db
  file delete -force test2.db
  sqlite db2 test2.db
  catchsql {
    ATTACH DATABASE 'test.db' AS orig;
    CREATE TRIGGER r1 AFTER INSERT ON orig.t1 BEGIN;
      SELECT 'no-op';
    END;
  } db2
} {1 {triggers may not be added to auxiliary database orig}}
do_test attach-5.2 {
  catchsql {
    CREATE TABLE t5(x,y);
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      SELECT 'no-op';
    END;
  } db2
} {0 {}}
do_test attach-5.3 {
  catchsql {
    DROP TRIGGER r5;
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      SELECT 'no-op' FROM orig.t1;
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database orig}}
do_test attach-5.4 {
  catchsql {
    CREATE TEMP TABLE t6(p,q,r);
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      SELECT 'no-op' FROM temp.t6;
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database temp}}
do_test attach-5.5 {
  catchsql {
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      SELECT 'no-op' || (SELECT * FROM temp.t6);
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database temp}}
do_test attach-5.6 {
  catchsql {
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      SELECT 'no-op' FROM t1 WHERE x<(SELECT min(x) FROM temp.t6);
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database temp}}
do_test attach-5.7 {
  catchsql {
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      SELECT 'no-op' FROM t1 GROUP BY 1 HAVING x<(SELECT min(x) FROM temp.t6);
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database temp}}
do_test attach-5.7 {
  catchsql {
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      SELECT max(1,x,(SELECT min(x) FROM temp.t6)) FROM t1;
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database temp}}
do_test attach-5.8 {
  catchsql {
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      INSERT INTO t1 VALUES((SELECT min(x) FROM temp.t6),5);
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database temp}}
do_test attach-5.9 {
  catchsql {
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      DELETE FROM t1 WHERE x<(SELECT min(x) FROM temp.t6);
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database temp}}

# Check to make sure we get a sensible error if unable to open
# the file that we are trying to attach.
#
do_test attach-6.1 {
  catchsql {
    ATTACH DATABASE 'no-such-file' AS nosuch;
  }
} {1 {cannot attach empty database: nosuch}}
file delete -force no-such-file
do_test attach-6.2 {
  sqlite dbx cannot-read
  dbx eval {CREATE TABLE t1(a,b,c)}
  dbx close
  catch {file attributes cannot-read -permission 0000}
  catch {file attributes cannot-read -readonly 1}
  catchsql {
    ATTACH DATABASE 'cannot-read' AS noread;
  }
} {1 {unable to open database: cannot-read}}
file delete -force cannot-read

for {set i 2} {$i<=15} {incr i} {
  catch {db$i close}
}
file delete -force test2.db


finish_test

Changes to test/format3.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
713
714
715
716
717
718
719
720

















721
#    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 the library is able to correctly
# handle file-format 3 (version 2.6.x) databases.
#
# $Id: format3.test,v 1.2 2002/12/04 21:50:16 drh Exp $

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

# Create a bunch of data to sort against
#
do_test format3-1.0 {
................................................................................
    INSERT INTO t7 VALUES(0,0,1);
    INSERT INTO t7 VALUES(0.0,0,2);
    INSERT INTO t7 VALUES(0,0.0,3);
    INSERT INTO t7 VALUES(0.0,0.0,4);
    SELECT DISTINCT x, y FROM t7 ORDER BY z;
  }
} {0 0}


















finish_test







|







 








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

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
#    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 the library is able to correctly
# handle file-format 3 (version 2.6.x) databases.
#
# $Id: format3.test,v 1.3 2003/06/03 01:47:12 drh Exp $

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

# Create a bunch of data to sort against
#
do_test format3-1.0 {
................................................................................
    INSERT INTO t7 VALUES(0,0,1);
    INSERT INTO t7 VALUES(0.0,0,2);
    INSERT INTO t7 VALUES(0,0.0,3);
    INSERT INTO t7 VALUES(0.0,0.0,4);
    SELECT DISTINCT x, y FROM t7 ORDER BY z;
  }
} {0 0}

# Make sure attempts to attach a format 3 database fail.
#
do_test format3-12.1 {
  file delete -force test2.db
  sqlite db2 test2.db
  catchsql {
    CREATE TABLE t8(x,y);
    ATTACH DATABASE 'test.db' AS format3;
  } db2;
} {1 {incompatible file format in auxiliary database: format3}}
do_test format3-12.2 {
  catchsql {
    ATTACH DATABASE 'test2.db' AS test2;
  }
} {1 {cannot attach auxiliary databases to an older format master database}}
db2 close

finish_test

Changes to test/misc1.test.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
514
515
516
517
518
519
520

521














522


523
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc1.test,v 1.21 2003/02/26 13:52:52 drh Exp $

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

# Test the creation and use of tables that have a large number
# of columns.
#
................................................................................
do_test misc1-16.6 {
  execsql {
    INSERT INTO test VALUES(NULL);
    SELECT rowid, a FROM test;
  }
} {1 1 5 5 6 6}




















finish_test







|







 







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

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc1.test,v 1.22 2003/06/03 01:47:12 drh Exp $

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

# Test the creation and use of tables that have a large number
# of columns.
#
................................................................................
do_test misc1-16.6 {
  execsql {
    INSERT INTO test VALUES(NULL);
    SELECT rowid, a FROM test;
  }
} {1 1 5 5 6 6}

# Ticket #333: Temp triggers that modify persistent tables.
#
do_test misc1-17.1 {
  execsql {
    BEGIN;
    CREATE TABLE RealTable(TestID INTEGER PRIMARY KEY, TestString TEXT);
    CREATE TEMP TABLE TempTable(TestID INTEGER PRIMARY KEY, TestString TEXT);
    CREATE TEMP TRIGGER trigTest_1 AFTER UPDATE ON TempTable BEGIN
      INSERT INTO RealTable(TestString) 
         SELECT new.TestString FROM TempTable LIMIT 1;
    END;
    INSERT INTO TempTable(TestString) VALUES ('1');
    INSERT INTO TempTable(TestString) VALUES ('2');
    UPDATE TempTable SET TestString = TestString + 1 WHERE TestID IN (1, 2);
    COMMIT;
    SELECT TestString FROM RealTable ORDER BY 1;
  }
} {2 3}

finish_test