/ Check-in [f4fcd46f]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Remove the test/dbselftest.c program. In its place, add the ".selftest" command to the CLI. The new CLI version is .selftest is slightly different in that it uses SHA3 hashing instead of SHA1, so the new is subtly incompatible with the old.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f4fcd46f08ba59d2a3e772cad98383129f648386
User & Date: drh 2017-03-09 22:00:33
Context
2017-03-10
01:05
Improvements to ".selftest --init". Tests are number in increments of 10 starting with 100. The tests are generated inside a SAVEPOINT. Errors are reported during test generation. Tests can be appended to existing tests. Add a test case to verify the schema. check-in: b044b152 user: drh tags: trunk
2017-03-09
22:00
Remove the test/dbselftest.c program. In its place, add the ".selftest" command to the CLI. The new CLI version is .selftest is slightly different in that it uses SHA3 hashing instead of SHA1, so the new is subtly incompatible with the old. check-in: f4fcd46f user: drh tags: trunk
18:13
Fix the ".dump" command to correctly extract tail data from corrupt WITHOUT ROWID tables. check-in: 6c627e50 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Makefile.in.

1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
	$(LTLINK) $(ST_OPT) -o $@ $(TOP)/test/speedtest1.c sqlite3.c $(TLIBS)

KV_OPT += -DSQLITE_DIRECT_OVERFLOW_READ

kvtest$(TEXE):	$(TOP)/test/kvtest.c sqlite3.c
	$(LTLINK) $(KV_OPT) -o $@ $(TOP)/test/kvtest.c sqlite3.c $(TLIBS)

DBSELFTEST_OPT += -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_FTS4

dbselftest$(TEXE):	$(TOP)/test/dbselftest.c sqlite3.c
	$(LTLINK) $(DBSELFTEST_OPT) -o $@ $(TOP)/test/dbselftest.c sqlite3.c $(TLIBS)

rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.lo 
	$(LTLINK) -I. -o $@ $(TOP)/ext/rbu/rbu.c sqlite3.lo $(TLIBS)

loadfts$(EXE): $(TOP)/tool/loadfts.c libsqlite3.la
	$(LTLINK) $(TOP)/tool/loadfts.c libsqlite3.la -o $@ $(TLIBS)

# This target will fail if the SQLite amalgamation contains any exported







<
<
<
<
<







1181
1182
1183
1184
1185
1186
1187





1188
1189
1190
1191
1192
1193
1194
	$(LTLINK) $(ST_OPT) -o $@ $(TOP)/test/speedtest1.c sqlite3.c $(TLIBS)

KV_OPT += -DSQLITE_DIRECT_OVERFLOW_READ

kvtest$(TEXE):	$(TOP)/test/kvtest.c sqlite3.c
	$(LTLINK) $(KV_OPT) -o $@ $(TOP)/test/kvtest.c sqlite3.c $(TLIBS)






rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.lo 
	$(LTLINK) -I. -o $@ $(TOP)/ext/rbu/rbu.c sqlite3.lo $(TLIBS)

loadfts$(EXE): $(TOP)/tool/loadfts.c libsqlite3.la
	$(LTLINK) $(TOP)/tool/loadfts.c libsqlite3.la -o $@ $(TLIBS)

# This target will fail if the SQLite amalgamation contains any exported

Changes to main.mk.

475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
...
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
DBFUZZ_OPT =
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
DBSELFTEST_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
DBSELFTEST_OPT += -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
ST_OPT = -DSQLITE_THREADSAFE=0

# This is the default Makefile target.  The objects listed here
# are what get build when you type just "make" with no arguments.
#
all:	sqlite3.h libsqlite3.a sqlite3$(EXE)

................................................................................

speedtest1$(EXE):	$(TOP)/test/speedtest1.c sqlite3.c
	$(TCCX) -I. $(ST_OPT) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.c $(THREADLIB) 

kvtest$(EXE):	$(TOP)/test/kvtest.c sqlite3.c
	$(TCCX) -I. $(KV_OPT) -o kvtest$(EXE) $(TOP)/test/kvtest.c sqlite3.c $(THREADLIB) 

dbselftest$(EXE):	$(TOP)/test/dbselftest.c sqlite3.c
	$(TCCX) -I. $(DBSELFTEST_OPT) -o dbselftest$(EXE) $(TOP)/test/dbselftest.c sqlite3.c $(THREADLIB)

rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.o 
	$(TCC) -I. -o rbu$(EXE) $(TOP)/ext/rbu/rbu.c sqlite3.o \
	  $(THREADLIB)

loadfts: $(TOP)/tool/loadfts.c libsqlite3.a
	$(TCC) $(TOP)/tool/loadfts.c libsqlite3.a -o loadfts $(THREADLIB)








<
<







 







<
<
<







475
476
477
478
479
480
481


482
483
484
485
486
487
488
...
896
897
898
899
900
901
902



903
904
905
906
907
908
909
SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
DBFUZZ_OPT =
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ


ST_OPT = -DSQLITE_THREADSAFE=0

# This is the default Makefile target.  The objects listed here
# are what get build when you type just "make" with no arguments.
#
all:	sqlite3.h libsqlite3.a sqlite3$(EXE)

................................................................................

speedtest1$(EXE):	$(TOP)/test/speedtest1.c sqlite3.c
	$(TCCX) -I. $(ST_OPT) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.c $(THREADLIB) 

kvtest$(EXE):	$(TOP)/test/kvtest.c sqlite3.c
	$(TCCX) -I. $(KV_OPT) -o kvtest$(EXE) $(TOP)/test/kvtest.c sqlite3.c $(THREADLIB) 




rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.o 
	$(TCC) -I. -o rbu$(EXE) $(TOP)/ext/rbu/rbu.c sqlite3.o \
	  $(THREADLIB)

loadfts: $(TOP)/tool/loadfts.c libsqlite3.a
	$(TCC) $(TOP)/tool/loadfts.c libsqlite3.a -o loadfts $(THREADLIB)

Changes to src/shell.c.

2050
2051
2052
2053
2054
2055
2056











































2057
2058
2059
2060
2061
2062
2063
....
5722
5723
5724
5725
5726
5727
5728






















































































































5729
5730
5731
5732
5733
5734
5735
** invokes for each row of a query result.
*/
static int callback(void *pArg, int nArg, char **azArg, char **azCol){
  /* since we don't have type info, call the shell_callback with a NULL value */
  return shell_callback(pArg, nArg, azArg, azCol, NULL);
}













































/*
** Set the destination table field of the ShellState structure to
** the name of the table given.  Escape any quote characters in the
** table name.
*/
static void set_table_name(ShellState *p, const char *zName){
................................................................................
        v = integerValue(azArg[i]);
        sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
        utf8_printf(p->out, "%s", zBuf);
      }
    }
  }else
#endif























































































































  if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
    if( nArg<2 || nArg>3 ){
      raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
      rc = 1;
    }
    if( nArg>=2 ){







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







 







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







2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
....
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
** invokes for each row of a query result.
*/
static int callback(void *pArg, int nArg, char **azArg, char **azCol){
  /* since we don't have type info, call the shell_callback with a NULL value */
  return shell_callback(pArg, nArg, azArg, azCol, NULL);
}

/*
** This is the callback routine from sqlite3_exec() that appends all
** output onto the end of a ShellText object.
*/
static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
  ShellText *p = (ShellText*)pArg;
  int i;
  if( p->n ) appendText(p, "|", 0);
  for(i=0; i<nArg; i++){
    if( i ) appendText(p, ",", 0);
    if( azArg[i] ) appendText(p, azArg[i], 0);
  }
  return 0;
}

/*
** Generate an appropriate SELFTEST table in the main database.
*/
static void createSelftestTable(ShellState *p){
  sqlite3_exec(p->db,
    "CREATE TABLE selftest(\n"
    "  tno INTEGER PRIMARY KEY,\n"   /* Test number */
    "  op TEXT,\n"                   /* Operator:  memo run */
    "  cmd TEXT,\n"                  /* Command text */
    "  ans TEXT\n"                   /* Desired answer */
    ");"
    "INSERT INTO selftest(op,cmd,ans)\n"
    "  SELECT 'run',"
    "    'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
    "        printf('%w',name) || '\" NOT INDEXED'',224))',\n"
    "    hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
    "  FROM (\n"
    "    SELECT name FROM sqlite_master\n"
    "     WHERE type='table'\n"
    "       AND name<>'selftest'\n"
    "       AND coalesce(rootpage,0)>0\n"
    "  )\n"
    " ORDER BY name;\n"
    "INSERT INTO selftest(op,cmd,ans)\n"
    "  VALUES('run','PRAGMA integrity_check','ok');\n"
    ,0,0,0);
}


/*
** Set the destination table field of the ShellState structure to
** the name of the table given.  Escape any quote characters in the
** table name.
*/
static void set_table_name(ShellState *p, const char *zName){
................................................................................
        v = integerValue(azArg[i]);
        sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
        utf8_printf(p->out, "%s", zBuf);
      }
    }
  }else
#endif

  if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
    int bIsInit = 0;         /* True to initialize the SELFTEST table */
    int bVerbose = 0;        /* Verbose output */
    int bSelftestExists;     /* True if SELFTEST already exists */
    char **azTest = 0;       /* Content of the SELFTEST table */
    int nRow = 0;            /* Number of rows in the SELFTEST table */
    int nCol = 4;            /* Number of columns in the SELFTEST table */
    int i;                   /* Loop counter */
    int nTest = 0;           /* Number of tests runs */
    int nErr = 0;            /* Number of errors seen */
    ShellText str;           /* Answer for a query */
    static char *azDefaultTest[] = {
       0, 0, 0, 0,
       "0", "memo", "Missing SELFTEST table - default checks only", "",
       "1", "run", "PRAGMA integrity_check", "ok"
    };
    static const int nDefaultRow = 2;

    open_db(p,0);
    for(i=1; i<nArg; i++){
      const char *z = azArg[i];
      if( z[0]=='-' && z[1]=='-' ) z++;
      if( strcmp(z,"-init")==0 ){
        bIsInit = 1;
      }else
      if( strcmp(z,"-v")==0 ){
        bVerbose++;
      }else
      {
        utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
                    azArg[i], azArg[0]);
        raw_printf(stderr, "Should be one of: --init -v\n");
        rc = 1;
        goto meta_command_exit;
      }
    }
    if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
           != SQLITE_OK ){
      bSelftestExists = 0;
    }else{
      bSelftestExists = 1;
    }
    if( bIsInit ){
      if( bSelftestExists ){
        raw_printf(stderr, "The selftest table already exists\n");
        rc = 1;
        goto meta_command_exit;
      }
      createSelftestTable(p);
      bSelftestExists = 1;
    }
    if( bSelftestExists ){
      rc = sqlite3_get_table(p->db, 
          "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
          &azTest, &nRow, &nCol, 0);
      if( rc ){
        raw_printf(stderr, "Error querying the selftest table\n");
        rc = 1;
        sqlite3_free_table(azTest);
        goto meta_command_exit;
      }else if( nRow==0 ){
        sqlite3_free_table(azTest);
        azTest = azDefaultTest;
        nRow = nDefaultRow;
      }
    }else{
      azTest = azDefaultTest;
      nRow = nDefaultRow;
    }
    initText(&str);
    appendText(&str, "x", 0);
    for(i=1; i<=nRow; i++){
      int tno = atoi(azTest[i*nCol]);
      const char *zOp = azTest[i*nCol+1];
      const char *zSql = azTest[i*nCol+2];
      const char *zAns = azTest[i*nCol+3];
  
      if( bVerbose>0 ){
        char *zQuote = sqlite3_mprintf("%q", zSql);
        printf("%d: %s %s\n", tno, zOp, zSql);
        sqlite3_free(zQuote);
      }
      if( strcmp(zOp,"memo")==0 ){
        utf8_printf(p->out, "%s\n", zSql);
      }else
      if( strcmp(zOp,"run")==0 ){
        char *zErrMsg = 0;
        str.n = 0;
        str.z[0] = 0;
        rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
        nTest++;
        if( bVerbose ){
          utf8_printf(p->out, "Result: %s\n", str.z);
        }
        if( rc || zErrMsg ){
          nErr++;
          rc = 1;
          utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
          sqlite3_free(zErrMsg);
        }else if( strcmp(zAns,str.z)!=0 ){
          nErr++;
          rc = 1;
          utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
          utf8_printf(p->out, "%d:      Got: [%s]\n", tno, str.z);
        }
      }else
      {
        utf8_printf(stderr,
          "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
        rc = 1;
        break;
      }
    }
    freeText(&str);
    if( azTest!=azDefaultTest ) sqlite3_free_table(azTest);
    utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
  }else

  if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
    if( nArg<2 || nArg>3 ){
      raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
      rc = 1;
    }
    if( nArg>=2 ){

Deleted test/dbselftest.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
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
204
205
206
207
208
209
210
211
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
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
273
274
275
276
277
278
279
280
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
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
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
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
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
/*
** 2017-02-07
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This program implements an SQLite database self-verification utility.
** Usage:
** 
**       dbselftest DATABASE ...
**
** This program reads the "selftest" table in DATABASE, in rowid order,
** and runs each of the tests described there, reporting results at the
** end.
**
** The intent of this program is to have a set of test database files that
** can be run using future versions of SQLite in order to verify that
** legacy database files continue to be readable.  In other words, the
** intent is to confirm that there have been no breaking changes in the 
** file format.  The program can also be used to verify that database files
** are fully compatible between different architectures.
**
** The selftest table looks like this:
**
**     CREATE TABLE selftest (
**       id INTEGER PRIMARY KEY,    -- Run tests in ascending order
**       op TEXT,                   -- "test", "regexp", "print", etc.
**       cmdtxt TEXT,               -- Usually the SQL to be run
**       expected TEXT              -- Expected results
**     );
**
*/
#include <assert.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"

static const char zHelp[] =
  "Usage: dbselftest [OPTIONS] DBFILE ...\n"
  "\n"
  "    --init         Create the selftest table\n"
  "    -q             Suppress most output.  Errors only\n"
  "    -v             Show extra output\n"
;


/******************************************************************************
** The following code from ext/misc/sha1.c
**
** Context for the SHA1 hash 
*/
typedef struct SHA1Context SHA1Context;
struct SHA1Context {
  unsigned int state[5];
  unsigned int count[2];
  unsigned char buffer[64];
};


#if __GNUC__ && (defined(__i386__) || defined(__x86_64__))
/*
 * GCC by itself only generates left rotates.  Use right rotates if
 * possible to be kinder to dinky implementations with iterative rotate
 * instructions.
 */
#define SHA_ROT(op, x, k) \
        ({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; })
#define rol(x,k) SHA_ROT("roll", x, k)
#define ror(x,k) SHA_ROT("rorl", x, k)

#else
/* Generic C equivalent */
#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
#define rol(x,k) SHA_ROT(x,k,32-(k))
#define ror(x,k) SHA_ROT(x,32-(k),k)
#endif


#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
    |(rol(block[i],8)&0x00FF00FF))
#define blk0be(i) block[i]
#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
    ^block[(i+2)&15]^block[i&15],1))

/*
 * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
 *
 * Rl0() for little-endian and Rb0() for big-endian.  Endianness is
 * determined at run-time.
 */
#define Rl0(v,w,x,y,z,i) \
    z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define Rb0(v,w,x,y,z,i) \
    z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R1(v,w,x,y,z,i) \
    z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R2(v,w,x,y,z,i) \
    z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
#define R3(v,w,x,y,z,i) \
    z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
#define R4(v,w,x,y,z,i) \
    z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);

/*
 * Hash a single 512-bit block. This is the core of the algorithm.
 */
void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
  unsigned int qq[5]; /* a, b, c, d, e; */
  static int one = 1;
  unsigned int block[16];
  memcpy(block, buffer, 64);
  memcpy(qq,state,5*sizeof(unsigned int));

#define a qq[0]
#define b qq[1]
#define c qq[2]
#define d qq[3]
#define e qq[4]

  /* Copy p->state[] to working vars */
  /*
  a = state[0];
  b = state[1];
  c = state[2];
  d = state[3];
  e = state[4];
  */

  /* 4 rounds of 20 operations each. Loop unrolled. */
  if( 1 == *(unsigned char*)&one ){
    Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3);
    Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7);
    Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11);
    Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15);
  }else{
    Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3);
    Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7);
    Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11);
    Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15);
  }
  R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
  R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
  R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
  R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
  R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
  R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
  R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
  R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
  R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
  R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
  R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
  R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
  R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
  R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
  R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
  R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);

  /* Add the working vars back into context.state[] */
  state[0] += a;
  state[1] += b;
  state[2] += c;
  state[3] += d;
  state[4] += e;

#undef a
#undef b
#undef c
#undef d
#undef e
}


/* Initialize a SHA1 context */
static void hash_init(SHA1Context *p){
  /* SHA1 initialization constants */
  p->state[0] = 0x67452301;
  p->state[1] = 0xEFCDAB89;
  p->state[2] = 0x98BADCFE;
  p->state[3] = 0x10325476;
  p->state[4] = 0xC3D2E1F0;
  p->count[0] = p->count[1] = 0;
}

/* Add new content to the SHA1 hash */
static void hash_step(
  SHA1Context *p,                 /* Add content to this context */
  const unsigned char *data,      /* Data to be added */
  unsigned int len                /* Number of bytes in data */
){
  unsigned int i, j;

  j = p->count[0];
  if( (p->count[0] += len << 3) < j ){
    p->count[1] += (len>>29)+1;
  }
  j = (j >> 3) & 63;
  if( (j + len) > 63 ){
    (void)memcpy(&p->buffer[j], data, (i = 64-j));
    SHA1Transform(p->state, p->buffer);
    for(; i + 63 < len; i += 64){
      SHA1Transform(p->state, &data[i]);
    }
    j = 0;
  }else{
    i = 0;
  }
  (void)memcpy(&p->buffer[j], &data[i], len - i);
}

/* Compute a string using sqlite3_vsnprintf() and hash it */
static void hash_step_vformat(
  SHA1Context *p,                 /* Add content to this context */
  const char *zFormat,
  ...
){
  va_list ap;
  int n;
  char zBuf[50];
  va_start(ap, zFormat);
  sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
  va_end(ap);
  n = (int)strlen(zBuf);
  hash_step(p, (unsigned char*)zBuf, n);
}


/* Add padding and compute the message digest.  Render the
** message digest as lower-case hexadecimal and put it into
** zOut[].  zOut[] must be at least 41 bytes long. */
static void hash_finish(
  SHA1Context *p,           /* The SHA1 context to finish and render */
  char *zOut                /* Store hexadecimal hash here */
){
  unsigned int i;
  unsigned char finalcount[8];
  unsigned char digest[20];
  static const char zEncode[] = "0123456789abcdef";

  for (i = 0; i < 8; i++){
    finalcount[i] = (unsigned char)((p->count[(i >= 4 ? 0 : 1)]
       >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
  }
  hash_step(p, (const unsigned char *)"\200", 1);
  while ((p->count[0] & 504) != 448){
    hash_step(p, (const unsigned char *)"\0", 1);
  }
  hash_step(p, finalcount, 8);  /* Should cause a SHA1Transform() */
  for (i = 0; i < 20; i++){
    digest[i] = (unsigned char)((p->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
  }
  for(i=0; i<20; i++){
    zOut[i*2] = zEncode[(digest[i]>>4)&0xf];
    zOut[i*2+1] = zEncode[digest[i] & 0xf];
  }
  zOut[i*2]= 0;
}

/*
** Implementation of the sha1(X) function.
**
** Return a lower-case hexadecimal rendering of the SHA1 hash of the
** argument X.  If X is a BLOB, it is hashed as is.  For all other
** types of input, X is converted into a UTF-8 string and the string
** is hash without the trailing 0x00 terminator.  The hash of a NULL
** value is NULL.
*/
static void sha1Func(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  SHA1Context cx;
  int eType = sqlite3_value_type(argv[0]);
  int nByte = sqlite3_value_bytes(argv[0]);
  char zOut[44];

  assert( argc==1 );
  if( eType==SQLITE_NULL ) return;
  hash_init(&cx);
  if( eType==SQLITE_BLOB ){
    hash_step(&cx, sqlite3_value_blob(argv[0]), nByte);
  }else{
    hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
  }
  hash_finish(&cx, zOut);
  sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
}

/*
** Run a prepared statement and compute the SHA1 hash on the
** result rows.
*/
static void sha1RunStatement(SHA1Context *pCtx, sqlite3_stmt *pStmt){
  int nCol = sqlite3_column_count(pStmt);
  const char *z = sqlite3_sql(pStmt);
  int n = (int)strlen(z);

  hash_step_vformat(pCtx,"S%d:",n);
  hash_step(pCtx,(unsigned char*)z,n);

  /* Compute a hash over the result of the query */
  while( SQLITE_ROW==sqlite3_step(pStmt) ){
    int i;
    hash_step(pCtx,(const unsigned char*)"R",1);
    for(i=0; i<nCol; i++){
      switch( sqlite3_column_type(pStmt,i) ){
        case SQLITE_NULL: {
          hash_step(pCtx, (const unsigned char*)"N",1);
          break;
        }
        case SQLITE_INTEGER: {
          sqlite3_uint64 u;
          int j;
          unsigned char x[9];
          sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
          memcpy(&u, &v, 8);
          for(j=8; j>=1; j--){
            x[j] = u & 0xff;
            u >>= 8;
          }
          x[0] = 'I';
          hash_step(pCtx, x, 9);
          break;
        }
        case SQLITE_FLOAT: {
          sqlite3_uint64 u;
          int j;
          unsigned char x[9];
          double r = sqlite3_column_double(pStmt,i);
          memcpy(&u, &r, 8);
          for(j=8; j>=1; j--){
            x[j] = u & 0xff;
            u >>= 8;
          }
          x[0] = 'F';
          hash_step(pCtx,x,9);
          break;
        }
        case SQLITE_TEXT: {
          int n2 = sqlite3_column_bytes(pStmt, i);
          const unsigned char *z2 = sqlite3_column_text(pStmt, i);
          hash_step_vformat(pCtx,"T%d:",n2);
          hash_step(pCtx, z2, n2);
          break;
        }
        case SQLITE_BLOB: {
          int n2 = sqlite3_column_bytes(pStmt, i);
          const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
          hash_step_vformat(pCtx,"B%d:",n2);
          hash_step(pCtx, z2, n2);
          break;
        }
      }
    }
  }
}

/*
** Run one or more statements of SQL.  Compute a SHA1 hash of the output.
*/
static int sha1Exec(
  sqlite3 *db,          /* Run against this database connection */
  const char *zSql,     /* The SQL to be run */
  char *zOut            /* Store the SHA1 hash as hexadecimal in this buffer */
){
  sqlite3_stmt *pStmt = 0;    /* A prepared statement */
  int rc;                     /* Result of an API call */
  SHA1Context cx;             /* The SHA1 hash context */

  hash_init(&cx);
  while( zSql[0] ){
    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
    if( rc ){
      sqlite3_finalize(pStmt);
      return rc;
    }
    sha1RunStatement(&cx, pStmt);
    sqlite3_finalize(pStmt);
  }
  hash_finish(&cx, zOut);
  return SQLITE_OK;
}

/*
** Implementation of the sha1_query(SQL) function.
**
** This function compiles and runs the SQL statement(s) given in the
** argument. The results are hashed using SHA1 and that hash is returned.
**
** The original SQL text is included as part of the hash.
**
** The hash is not just a concatenation of the outputs.  Each query
** is delimited and each row and value within the query is delimited,
** with all values being marked with their datatypes.
*/
static void sha1QueryFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zSql = (const char*)sqlite3_value_text(argv[0]);
  sqlite3_stmt *pStmt = 0;
  int rc;
  SHA1Context cx;
  char zOut[44];

  assert( argc==1 );
  if( zSql==0 ) return;
  hash_init(&cx);
  while( zSql[0] ){
    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
    if( rc ){
      char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
                                   zSql, sqlite3_errmsg(db));
      sqlite3_finalize(pStmt);
      sqlite3_result_error(context, zMsg, -1);
      sqlite3_free(zMsg);
      return;
    }
    if( !sqlite3_stmt_readonly(pStmt) ){
      char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
      sqlite3_finalize(pStmt);
      sqlite3_result_error(context, zMsg, -1);
      sqlite3_free(zMsg);
      return;
    }
    sha1RunStatement(&cx, pStmt);
    sqlite3_finalize(pStmt);
  }
  hash_finish(&cx, zOut);
  sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
}
/* End of ext/misc/sha1.c
******************************************************************************/

/* How much output to display */
#define VOLUME_MIN          0
#define VOLUME_OFF          0
#define VOLUME_ERROR_ONLY   1
#define VOLUME_LOW          2
#define VOLUME_ECHO         3
#define VOLUME_VERBOSE      4
#define VOLUME_MAX          4

/* A string accumulator
*/
typedef struct Str {
  char *z;             /* Accumulated text */
  int n;               /* Bytes of z[] used so far */
  int nAlloc;          /* Bytes allocated for z[] */
} Str;

/* Append text to the Str object
*/
static void strAppend(Str *p, const char *z){
  int n = (int)strlen(z);
  if( p->n+n >= p->nAlloc ){
    p->nAlloc += p->n+n + 100;
    p->z = sqlite3_realloc(p->z, p->nAlloc);
    if( z==0 ){
      printf("Could not allocate %d bytes\n", p->nAlloc);
      exit(1);
    }
  }
  memcpy(p->z+p->n, z, n+1);
  p->n += n;
}

/* This is an sqlite3_exec() callback that will capture all
** output in a Str.
**
** Columns are separated by ",".  Rows are separated by "|".
*/
static int execCallback(void *pStr, int argc, char **argv, char **colv){
  int i;
  Str *p = (Str*)pStr;
  if( p->n ) strAppend(p, "|");
  for(i=0; i<argc; i++){
    const char *z = (const char*)argv[i];
    if( z==0 ) z = "NULL";
    if( i>0 ) strAppend(p, ",");
    strAppend(p, z);
  }
  return 0;
}

/*
** Run an SQL statement constructing using sqlite3_vmprintf().
** Return the number of errors.
*/
static int runSql(sqlite3 *db, const char *zFormat, ...){
  char *zSql;
  char *zErr = 0;
  int rc;
  int nErr = 0;
  va_list ap;

  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  if( zSql==0 ){
    printf("Out of memory\n");
    exit(1);
  }
  rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
  if( rc || zErr ){
    printf("SQL error in [%s]: code=%d: %s\n", zSql, rc, zErr);
    nErr++;
  }
  sqlite3_free(zSql);
  return nErr;
}

/*
** Generate a prepared statement using a formatted string.
*/
static sqlite3_stmt *prepareSql(sqlite3 *db, const char *zFormat, ...){
  char *zSql;
  int rc;
  sqlite3_stmt *pStmt = 0;
  va_list ap;

  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  if( zSql==0 ){
    printf("Out of memory\n");
    exit(1);
  }
  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  if( rc ){
    printf("SQL error in [%s]: code=%d: %s\n", zSql, rc, sqlite3_errmsg(db));
    sqlite3_finalize(pStmt);
    pStmt = 0;
  }
  sqlite3_free(zSql);
  return pStmt;
}

/*
** Construct the standard selftest configuration for the database.
*/
static int buildSelftestTable(sqlite3 *db){
  int rc;
  sqlite3_stmt *pStmt;
  int tno = 110;
  char *zSql;
  char zHash[50];

  rc = runSql(db,
     "CREATE TABLE IF NOT EXISTS selftest(\n"
     "  tno INTEGER PRIMARY KEY,  -- test number\n"
     "  op TEXT,                  -- what kind of test\n"
     "  sql TEXT,                 -- SQL text for the test\n"
     "  ans TEXT                  -- expected answer\n"
     ");"
     "INSERT INTO selftest"
     " VALUES(100,'memo','Hashes generated using --init',NULL);"
  );
  if( rc ) return 1;
  tno = 110;
  zSql = "SELECT type,name,tbl_name,sql FROM sqlite_master ORDER BY name";
  sha1Exec(db, zSql, zHash);
  rc = runSql(db, 
      "INSERT INTO selftest(tno,op,sql,ans)"
      " VALUES(%d,'sha1',%Q,%Q)", tno, zSql, zHash);
  tno += 10;
  pStmt = prepareSql(db,
    "SELECT lower(name) FROM sqlite_master"
    " WHERE type='table' AND sql NOT GLOB 'CREATE VIRTUAL*'"
    "   AND name<>'selftest'"
    " ORDER BY 1");
  if( pStmt==0 ) return 1;
  while( SQLITE_ROW==sqlite3_step(pStmt) ){
    zSql = sqlite3_mprintf("SELECT * FROM \"%w\" NOT INDEXED",
                            sqlite3_column_text(pStmt, 0));
    if( zSql==0 ){
      printf("Of of memory\n");
      exit(1);
    }
    sha1Exec(db, zSql, zHash);
    rc = runSql(db,
      "INSERT INTO selftest(tno,op,sql,ans)"
      " VALUES(%d,'sha1',%Q,%Q)", tno, zSql, zHash);
    tno += 10;
    sqlite3_free(zSql);
    if( rc ) break;
  }
  sqlite3_finalize(pStmt);
  if( rc ) return 1;
  rc = runSql(db,
     "INSERT INTO selftest(tno,op,sql,ans)"
     " VALUES(%d,'run','PRAGMA integrity_check','ok');", tno);
  if( rc ) return 1;
  return rc;
}

/*
** Return true if the named table exists
*/
static int tableExists(sqlite3 *db, const char *zTab){
  return sqlite3_table_column_metadata(db, "main", zTab, 0, 0, 0, 0, 0, 0)
            == SQLITE_OK;
}

/*
** Default selftest table content, for use when there is no selftest table
*/
static char *azDefaultTest[] = {
   0, 0, 0, 0,
   "0", "memo", "Missing SELFTEST table - default checks only", "",
   "1", "run", "PRAGMA integrity_check", "ok"
};

int main(int argc, char **argv){
  int eVolume = VOLUME_LOW;    /* How much output to display */
  const char **azDb = 0;       /* Name of the database file */
  int nDb = 0;                 /* Number of database files to check */
  int doInit = 0;              /* True if --init is present */
  sqlite3 *db = 0;             /* Open database connection */
  int rc;                      /* Return code from API calls */
  char *zErrMsg = 0;           /* An error message return */
  char **azTest;               /* Content of the selftest table */
  int nRow = 0, nCol = 0;      /* Rows and columns in azTest[] */
  int i;                       /* Loop counter */
  int nErr = 0;                /* Number of errors */
  int iDb;                     /* Loop counter for databases */
  Str str;                     /* Result accumulator */
  int nTest = 0;               /* Number of tests run */

  for(i=1; i<argc; i++){
    const char *z = argv[i];
    if( z[0]=='-' ){
      if( z[1]=='-' ) z++;
      if( strcmp(z, "-help")==0 ){
        printf("%s", zHelp);
        return 0;
      }else
      if( strcmp(z, "-init")==0 ){
        doInit = 1;
      }else
      if( strcmp(z, "-a")==0 ){
        if( eVolume>VOLUME_MIN) eVolume--;
      }else
      if( strcmp(z, "-v")==0 ){
        if( eVolume<VOLUME_MAX) eVolume++;
      }else
      {
        printf("unknown option: \"%s\"\nUse --help for more information\n",
               argv[i]);
        return 1;
      }
    }else{
      nDb++;
      azDb = sqlite3_realloc(azDb, nDb*sizeof(azDb[0]));
      if( azDb==0 ){
        printf("out of memory\n");
        exit(1);
      }
      azDb[nDb-1] = argv[i];
    }
  }
  if( nDb==0 ){
    printf("No databases specified.  Use --help for more info\n");
    return 1;
  }
  if( eVolume>=VOLUME_LOW ){
    printf("SQLite %s\n", sqlite3_sourceid());
  }
  memset(&str, 0, sizeof(str));
  strAppend(&str, "\n");
  for(iDb=0; iDb<nDb; iDb++, sqlite3_close(db)){
    rc = sqlite3_open_v2(azDb[iDb], &db, 
          doInit ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY, 0);
    if( rc ){
      printf("Cannot open \"%s\": %s\n", azDb[iDb], sqlite3_errmsg(db));
      return 1;
    }
    rc = sqlite3_create_function(db, "sha1", 1, SQLITE_UTF8, 0,
                                 sha1Func, 0, 0);
    if( rc==SQLITE_OK ){
      rc = sqlite3_create_function(db, "sha1_query", 1, SQLITE_UTF8, 0,
                                   sha1QueryFunc, 0, 0);
    }
    if( rc ){
      printf("Initialization error: %s\n", sqlite3_errmsg(db));
      sqlite3_close(db);
      return 1;
    }
    if( doInit && !tableExists(db, "selftest") ){
       buildSelftestTable(db);
    }
    if( !tableExists(db, "selftest") ){
      azTest = azDefaultTest;
      nCol = 4;
      nRow = 2;
    }else{
      rc = sqlite3_get_table(db, 
          "SELECT tno,op,sql,ans FROM selftest ORDER BY tno",
          &azTest, &nRow, &nCol, &zErrMsg);
      if( rc || zErrMsg ){
        printf("Error querying selftest: %s\n", zErrMsg);
        sqlite3_free_table(azTest);
        continue;
      }
    }
    for(i=1; i<=nRow; i++){
      int tno = atoi(azTest[i*nCol]);
      const char *zOp = azTest[i*nCol+1];
      const char *zSql = azTest[i*nCol+2];
      const char *zAns = azTest[i*nCol+3];
  
      if( eVolume>=VOLUME_ECHO ){
        char *zQuote = sqlite3_mprintf("%q", zSql);
        printf("%d: %s %s\n", tno, zOp, zSql);
        sqlite3_free(zQuote);
      }
      if( strcmp(zOp,"memo")==0 ){
        if( eVolume>=VOLUME_LOW ){
          printf("%s: %s\n", azDb[iDb], zSql);
        }
      }else
      if( strcmp(zOp,"sha1")==0 ){
        char zOut[44];
        rc = sha1Exec(db, zSql, zOut);
        nTest++;
        if( eVolume>=VOLUME_VERBOSE ){
          printf("Result: %s\n", zOut);
        }
        if( rc ){
          nErr++;
          if( eVolume>=VOLUME_ERROR_ONLY ){
            printf("%d: error-code-%d: %s\n", tno, rc, sqlite3_errmsg(db));
          }
        }else if( strcmp(zAns,zOut)!=0 ){
          nErr++;
          if( eVolume>=VOLUME_ERROR_ONLY ){
            printf("%d: Expected: [%s]\n", tno, zAns);
            printf("%d:      Got: [%s]\n", tno, zOut);
          }
        }
      }else
      if( strcmp(zOp,"run")==0 ){
        str.n = 0;
        str.z[0] = 0;
        zErrMsg = 0;
        rc = sqlite3_exec(db, zSql, execCallback, &str, &zErrMsg);
        nTest++;
        if( eVolume>=VOLUME_VERBOSE ){
          printf("Result: %s\n", str.z);
        }
        if( rc || zErrMsg ){
          nErr++;
          if( eVolume>=VOLUME_ERROR_ONLY ){
            printf("%d: error-code-%d: %s\n", tno, rc, zErrMsg);
          }
          sqlite3_free(zErrMsg);
        }else if( strcmp(zAns,str.z)!=0 ){
          nErr++;
          if( eVolume>=VOLUME_ERROR_ONLY ){
            printf("%d: Expected: [%s]\n", tno, zAns);
            printf("%d:      Got: [%s]\n", tno, str.z);
          }
        }
      }else
      {
        printf("Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
        return 1;
      }
    }
    if( azTest!=azDefaultTest ) sqlite3_free_table(azTest);
  }
  if( eVolume>=VOLUME_LOW || (nErr>0 && eVolume>=VOLUME_ERROR_ONLY) ){
    printf("%d errors out of %d tests on %d databases\n", nErr, nTest, nDb);
  }
  return nErr;
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<