Fossil SCM

Merge trunk

jan.nijtmans 2016-01-06 20:49 pending-review merge
Commit 9e1fa626e47f1479283cc21c07c54a6b3e4a2698
+86 -22
--- src/attach.c
+++ src/attach.c
@@ -26,28 +26,36 @@
2626
** List attachments.
2727
**
2828
** tkt=TICKETUUID
2929
** page=WIKIPAGE
3030
**
31
-** Either one of tkt= or page= are supplied or neither but not both.
32
-** If neither are given, all attachments are listed. If one is given,
33
-** only attachments for the designated ticket or wiki page are shown.
34
-** TICKETUUID must be complete
31
+** At most one of technote=, tkt= or page= are supplied.
32
+** If none is given, all attachments are listed. If one is given,
33
+** only attachments for the designated technote, ticket or wiki page
34
+** are shown. TECHNOTEUUID and TICKETUUID may be just a prefix of the
35
+** relevant tech note or ticket, in which case all attachments of all
36
+** tech notes or tickets with the prefix will be listed.
3537
*/
3638
void attachlist_page(void){
3739
const char *zPage = P("page");
3840
const char *zTkt = P("tkt");
41
+ const char *zTechNote = P("technote");
3942
Blob sql;
4043
Stmt q;
4144
4245
if( zPage && zTkt ) zTkt = 0;
4346
login_check_credentials();
4447
blob_zero(&sql);
4548
blob_append_sql(&sql,
4649
"SELECT datetime(mtime,toLocal()), src, target, filename,"
4750
" comment, user,"
48
- " (SELECT uuid FROM blob WHERE rid=attachid), attachid"
51
+ " (SELECT uuid FROM blob WHERE rid=attachid), attachid,"
52
+ " (CASE WHEN 'tkt-'||target IN (SELECT tagname FROM tag)"
53
+ " THEN 1"
54
+ " WHEN 'event-'||target IN (SELECT tagname FROM tag)"
55
+ " THEN 2"
56
+ " ELSE 0 END)"
4957
" FROM attachment"
5058
);
5159
if( zPage ){
5260
if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
5361
style_header("Attachments To %h", zPage);
@@ -54,10 +62,15 @@
5462
blob_append_sql(&sql, " WHERE target=%Q", zPage);
5563
}else if( zTkt ){
5664
if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
5765
style_header("Attachments To Ticket %S", zTkt);
5866
blob_append_sql(&sql, " WHERE target GLOB '%q*'", zTkt);
67
+ }else if( zTechNote ){
68
+ if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
69
+ style_header("Attachments to Tech Note %S", zTechNote);
70
+ blob_append_sql(&sql, " WHERE target GLOB '%q*'",
71
+ zTechNote);
5972
}else{
6073
if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ){
6174
login_needed(g.anon.RdTkt || g.anon.RdWiki);
6275
return;
6376
}
@@ -73,21 +86,25 @@
7386
const char *zFilename = db_column_text(&q, 3);
7487
const char *zComment = db_column_text(&q, 4);
7588
const char *zUser = db_column_text(&q, 5);
7689
const char *zUuid = db_column_text(&q, 6);
7790
int attachid = db_column_int(&q, 7);
91
+ // type 0 is a wiki page, 1 is a ticket, 2 is a tech note
92
+ int type = db_column_int(&q, 8);
7893
const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
7994
int i;
8095
char *zUrlTail;
8196
for(i=0; zFilename[i]; i++){
8297
if( zFilename[i]=='/' && zFilename[i+1]!=0 ){
8398
zFilename = &zFilename[i+1];
8499
i = -1;
85100
}
86101
}
87
- if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
102
+ if( type==1 ){
88103
zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
104
+ }else if( type==2 ){
105
+ zUrlTail = mprintf("technote=%s&file=%t", zTarget, zFilename);
89106
}else{
90107
zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
91108
}
92109
@ <li><p>
93110
@ Attachment %z(href("%R/ainfo/%!S",zUuid))%S(zUuid)</a>
@@ -98,19 +115,22 @@
98115
@ [<a href="%R/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br />
99116
if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++;
100117
if( zComment && zComment[0] ){
101118
@ %!W(zComment)<br />
102119
}
103
- if( zPage==0 && zTkt==0 ){
120
+ if( zPage==0 && zTkt==0 && zTechNote==0 ){
104121
if( zSrc==0 || zSrc[0]==0 ){
105122
zSrc = "Deleted from";
106123
}else {
107124
zSrc = "Added to";
108125
}
109
- if( strlen(zTarget)==UUID_SIZE && validate16(zTarget, UUID_SIZE) ){
126
+ if( type==1 ){
110127
@ %s(zSrc) ticket <a href="%R/tktview?name=%s(zTarget)">
111128
@ %S(zTarget)</a>
129
+ }else if( type==2 ){
130
+ @ %s(zSrc) tech note <a href="%R/technote/%s(zTarget)">
131
+ @ %S(zTarget)</a>
112132
}else{
113133
@ %s(zSrc) wiki page <a href="%R/wiki?name=%t(zTarget)">
114134
@ %h(zTarget)</a>
115135
}
116136
}else{
@@ -138,31 +158,35 @@
138158
** Download or display an attachment.
139159
** Query parameters:
140160
**
141161
** tkt=TICKETUUID
142162
** page=WIKIPAGE
163
+** technote=TECHNOTEUUID
143164
** file=FILENAME
144165
** attachid=ID
145166
**
146167
*/
147168
void attachview_page(void){
148169
const char *zPage = P("page");
149170
const char *zTkt = P("tkt");
171
+ const char *zTechNote = P("technote");
150172
const char *zFile = P("file");
151173
const char *zTarget = 0;
152174
int attachid = atoi(PD("attachid","0"));
153175
char *zUUID;
154176
155
- if( zPage && zTkt ) zTkt = 0;
156177
if( zFile==0 ) fossil_redirect_home();
157178
login_check_credentials();
158179
if( zPage ){
159180
if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
160181
zTarget = zPage;
161182
}else if( zTkt ){
162183
if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
163184
zTarget = zTkt;
185
+ }else if( zTechNote ){
186
+ if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
187
+ zTarget = zTechNote;
164188
}else{
165189
fossil_redirect_home();
166190
}
167191
if( attachid>0 ){
168192
zUUID = db_text(0,
@@ -186,18 +210,19 @@
186210
}else if( zUUID[0]=='x' ){
187211
style_header("Missing");
188212
@ Attachment has been deleted
189213
style_footer();
190214
return;
191
- }
192
- g.perm.Read = 1;
193
- cgi_replace_parameter("name",zUUID);
194
- if( fossil_strcmp(g.zPath,"attachview")==0 ){
195
- artifact_page();
196215
}else{
197
- cgi_replace_parameter("m", mimetype_from_name(zFile));
198
- rawartifact_page();
216
+ g.perm.Read = 1;
217
+ cgi_replace_parameter("name",zUUID);
218
+ if( fossil_strcmp(g.zPath,"attachview")==0 ){
219
+ artifact_page();
220
+ }else{
221
+ cgi_replace_parameter("m", mimetype_from_name(zFile));
222
+ rawartifact_page();
223
+ }
199224
}
200225
}
201226
202227
/*
203228
** Save an attachment control artifact into the repository
@@ -228,27 +253,34 @@
228253
** WEBPAGE: attachadd
229254
** Add a new attachment.
230255
**
231256
** tkt=TICKETUUID
232257
** page=WIKIPAGE
258
+** technote=TECHNOTEUUID
233259
** from=URL
234260
**
235261
*/
236262
void attachadd_page(void){
237263
const char *zPage = P("page");
238264
const char *zTkt = P("tkt");
265
+ const char *zTechNote = P("technote");
239266
const char *zFrom = P("from");
240267
const char *aContent = P("f");
241268
const char *zName = PD("f:filename","unknown");
242269
const char *zTarget;
243
- const char *zTargetType;
270
+ char *zTargetType;
244271
int szContent = atoi(PD("f:bytes","0"));
245272
int goodCaptcha = 1;
246273
247274
if( P("cancel") ) cgi_redirect(zFrom);
248
- if( zPage && zTkt ) fossil_redirect_home();
249
- if( zPage==0 && zTkt==0 ) fossil_redirect_home();
275
+ if( (zPage && zTkt)
276
+ || (zPage && zTechNote)
277
+ || (zTkt && zTechNote)
278
+ ){
279
+ fossil_redirect_home();
280
+ }
281
+ if( zPage==0 && zTkt==0 && zTechNote==0) fossil_redirect_home();
250282
login_check_credentials();
251283
if( zPage ){
252284
if( g.perm.ApndWiki==0 || g.perm.Attach==0 ){
253285
login_needed(g.anon.ApndWiki && g.anon.Attach);
254286
return;
@@ -257,10 +289,24 @@
257289
fossil_redirect_home();
258290
}
259291
zTarget = zPage;
260292
zTargetType = mprintf("Wiki Page <a href=\"%R/wiki?name=%h\">%h</a>",
261293
zPage, zPage);
294
+ }else if ( zTechNote ){
295
+ if( g.perm.Write==0 || g.perm.ApndWiki==0 || g.perm.Attach==0 ){
296
+ login_needed(g.anon.Write && g.anon.ApndWiki && g.anon.Attach);
297
+ return;
298
+ }
299
+ if( !db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'", zTechNote) ){
300
+ zTechNote = db_text(0, "SELECT substr(tagname,7) FROM tag"
301
+ " WHERE tagname GLOB 'event-%q*'", zTechNote);
302
+ if( zTechNote==0) fossil_redirect_home();
303
+ }
304
+ zTarget = zTechNote;
305
+ zTargetType = mprintf("Tech Note <a href=\"%R/technote/%h\">%h</a>",
306
+ zTechNote, zTechNote);
307
+
262308
}else{
263309
if( g.perm.ApndTkt==0 || g.perm.Attach==0 ){
264310
login_needed(g.anon.ApndTkt && g.anon.Attach);
265311
return;
266312
}
@@ -340,10 +386,12 @@
340386
@ <input type="file" name="f" size="60" /><br />
341387
@ Description:<br />
342388
@ <textarea name="comment" cols="80" rows="5" wrap="virtual"></textarea><br />
343389
if( zTkt ){
344390
@ <input type="hidden" name="tkt" value="%h(zTkt)" />
391
+ }else if( zTechNote ){
392
+ @ <input type="hidden" name="technote" value="%h(zTechNote)" />
345393
}else{
346394
@ <input type="hidden" name="page" value="%h(zPage)" />
347395
}
348396
@ <input type="hidden" name="from" value="%h(zFrom)" />
349397
@ <input type="submit" name="ok" value="Add Attachment" />
@@ -350,10 +398,11 @@
350398
@ <input type="submit" name="cancel" value="Cancel" />
351399
@ </div>
352400
captcha_generate(0);
353401
@ </form>
354402
style_footer();
403
+ fossil_free(zTargetType);
355404
}
356405
357406
/*
358407
** WEBPAGE: ainfo
359408
** URL: /ainfo?name=ARTIFACTID
@@ -364,15 +413,16 @@
364413
int rid; /* RID for the control artifact */
365414
int ridSrc; /* RID for the attached file */
366415
char *zDate; /* Date attached */
367416
const char *zUuid; /* UUID of the control artifact */
368417
Manifest *pAttach; /* Parse of the control artifact */
369
- const char *zTarget; /* Wiki or ticket attached to */
418
+ const char *zTarget; /* Wiki, ticket or tech note attached to */
370419
const char *zSrc; /* UUID of the attached file */
371420
const char *zName; /* Name of the attached file */
372421
const char *zDesc; /* Description of the attached file */
373422
const char *zWikiName = 0; /* Wiki page name when attached to Wiki */
423
+ const char *zTNUuid = 0; /* Tech Note ID when attached to tech note */
374424
const char *zTktUuid = 0; /* Ticket ID when attached to a ticket */
375425
int modPending; /* True if awaiting moderation */
376426
const char *zModAction; /* Moderation action or NULL */
377427
int isModerator; /* TRUE if user is the moderator */
378428
const char *zMime; /* MIME Type */
@@ -422,15 +472,23 @@
422472
zWikiName = zTarget;
423473
if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
424474
if( g.perm.WrWiki ){
425475
style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
426476
}
477
+ }else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",zTarget) ){
478
+ zTNUuid = zTarget;
479
+ if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
480
+ if( g.perm.Write && g.perm.WrWiki ){
481
+ style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
482
+ }
427483
}
428484
zDate = db_text(0, "SELECT datetime(%.12f)", pAttach->rDate);
429485
430486
if( P("confirm")
431
- && ((zTktUuid && g.perm.WrTkt) || (zWikiName && g.perm.WrWiki))
487
+ && ((zTktUuid && g.perm.WrTkt) ||
488
+ (zWikiName && g.perm.WrWiki) ||
489
+ (zTNUuid && g.perm.Write && g.perm.WrWiki))
432490
){
433491
int i, n, rid;
434492
char *zDate;
435493
Blob manifest;
436494
Blob cksum;
@@ -454,11 +512,13 @@
454512
db_end_transaction(0);
455513
@ <p>The attachment below has been deleted.</p>
456514
}
457515
458516
if( P("del")
459
- && ((zTktUuid && g.perm.WrTkt) || (zWikiName && g.perm.WrWiki))
517
+ && ((zTktUuid && g.perm.WrTkt) ||
518
+ (zWikiName && g.perm.WrWiki) ||
519
+ (zTNUuid && g.perm.Write && g.perm.WrWiki))
460520
){
461521
form_begin(0, "%R/ainfo/%!S", zUuid);
462522
@ <p>Confirm you want to delete the attachment shown below.
463523
@ <input type="submit" name="confirm" value="Confirm">
464524
@ </form>
@@ -502,10 +562,14 @@
502562
}
503563
if( zTktUuid ){
504564
@ <tr><th>Ticket:</th>
505565
@ <td>%z(href("%R/tktview/%s",zTktUuid))%s(zTktUuid)</a></td></tr>
506566
}
567
+ if( zTNUuid ){
568
+ @ <tr><th>Tech Note:</th>
569
+ @ <td>%z(href("%R/technote/%s",zTNUuid))%s(zTNUuid)</a></td></tr>
570
+ }
507571
if( zWikiName ){
508572
@ <tr><th>Wiki&nbsp;Page:</th>
509573
@ <td>%z(href("%R/wiki?name=%t",zWikiName))%h(zWikiName)</a></td></tr>
510574
}
511575
@ <tr><th>Date:</th><td>
512576
--- src/attach.c
+++ src/attach.c
@@ -26,28 +26,36 @@
26 ** List attachments.
27 **
28 ** tkt=TICKETUUID
29 ** page=WIKIPAGE
30 **
31 ** Either one of tkt= or page= are supplied or neither but not both.
32 ** If neither are given, all attachments are listed. If one is given,
33 ** only attachments for the designated ticket or wiki page are shown.
34 ** TICKETUUID must be complete
 
 
35 */
36 void attachlist_page(void){
37 const char *zPage = P("page");
38 const char *zTkt = P("tkt");
 
39 Blob sql;
40 Stmt q;
41
42 if( zPage && zTkt ) zTkt = 0;
43 login_check_credentials();
44 blob_zero(&sql);
45 blob_append_sql(&sql,
46 "SELECT datetime(mtime,toLocal()), src, target, filename,"
47 " comment, user,"
48 " (SELECT uuid FROM blob WHERE rid=attachid), attachid"
 
 
 
 
 
49 " FROM attachment"
50 );
51 if( zPage ){
52 if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
53 style_header("Attachments To %h", zPage);
@@ -54,10 +62,15 @@
54 blob_append_sql(&sql, " WHERE target=%Q", zPage);
55 }else if( zTkt ){
56 if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
57 style_header("Attachments To Ticket %S", zTkt);
58 blob_append_sql(&sql, " WHERE target GLOB '%q*'", zTkt);
 
 
 
 
 
59 }else{
60 if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ){
61 login_needed(g.anon.RdTkt || g.anon.RdWiki);
62 return;
63 }
@@ -73,21 +86,25 @@
73 const char *zFilename = db_column_text(&q, 3);
74 const char *zComment = db_column_text(&q, 4);
75 const char *zUser = db_column_text(&q, 5);
76 const char *zUuid = db_column_text(&q, 6);
77 int attachid = db_column_int(&q, 7);
 
 
78 const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
79 int i;
80 char *zUrlTail;
81 for(i=0; zFilename[i]; i++){
82 if( zFilename[i]=='/' && zFilename[i+1]!=0 ){
83 zFilename = &zFilename[i+1];
84 i = -1;
85 }
86 }
87 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
88 zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
 
 
89 }else{
90 zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
91 }
92 @ <li><p>
93 @ Attachment %z(href("%R/ainfo/%!S",zUuid))%S(zUuid)</a>
@@ -98,19 +115,22 @@
98 @ [<a href="%R/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br />
99 if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++;
100 if( zComment && zComment[0] ){
101 @ %!W(zComment)<br />
102 }
103 if( zPage==0 && zTkt==0 ){
104 if( zSrc==0 || zSrc[0]==0 ){
105 zSrc = "Deleted from";
106 }else {
107 zSrc = "Added to";
108 }
109 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget, UUID_SIZE) ){
110 @ %s(zSrc) ticket <a href="%R/tktview?name=%s(zTarget)">
111 @ %S(zTarget)</a>
 
 
 
112 }else{
113 @ %s(zSrc) wiki page <a href="%R/wiki?name=%t(zTarget)">
114 @ %h(zTarget)</a>
115 }
116 }else{
@@ -138,31 +158,35 @@
138 ** Download or display an attachment.
139 ** Query parameters:
140 **
141 ** tkt=TICKETUUID
142 ** page=WIKIPAGE
 
143 ** file=FILENAME
144 ** attachid=ID
145 **
146 */
147 void attachview_page(void){
148 const char *zPage = P("page");
149 const char *zTkt = P("tkt");
 
150 const char *zFile = P("file");
151 const char *zTarget = 0;
152 int attachid = atoi(PD("attachid","0"));
153 char *zUUID;
154
155 if( zPage && zTkt ) zTkt = 0;
156 if( zFile==0 ) fossil_redirect_home();
157 login_check_credentials();
158 if( zPage ){
159 if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
160 zTarget = zPage;
161 }else if( zTkt ){
162 if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
163 zTarget = zTkt;
 
 
 
164 }else{
165 fossil_redirect_home();
166 }
167 if( attachid>0 ){
168 zUUID = db_text(0,
@@ -186,18 +210,19 @@
186 }else if( zUUID[0]=='x' ){
187 style_header("Missing");
188 @ Attachment has been deleted
189 style_footer();
190 return;
191 }
192 g.perm.Read = 1;
193 cgi_replace_parameter("name",zUUID);
194 if( fossil_strcmp(g.zPath,"attachview")==0 ){
195 artifact_page();
196 }else{
197 cgi_replace_parameter("m", mimetype_from_name(zFile));
198 rawartifact_page();
 
 
 
 
 
 
199 }
200 }
201
202 /*
203 ** Save an attachment control artifact into the repository
@@ -228,27 +253,34 @@
228 ** WEBPAGE: attachadd
229 ** Add a new attachment.
230 **
231 ** tkt=TICKETUUID
232 ** page=WIKIPAGE
 
233 ** from=URL
234 **
235 */
236 void attachadd_page(void){
237 const char *zPage = P("page");
238 const char *zTkt = P("tkt");
 
239 const char *zFrom = P("from");
240 const char *aContent = P("f");
241 const char *zName = PD("f:filename","unknown");
242 const char *zTarget;
243 const char *zTargetType;
244 int szContent = atoi(PD("f:bytes","0"));
245 int goodCaptcha = 1;
246
247 if( P("cancel") ) cgi_redirect(zFrom);
248 if( zPage && zTkt ) fossil_redirect_home();
249 if( zPage==0 && zTkt==0 ) fossil_redirect_home();
 
 
 
 
 
250 login_check_credentials();
251 if( zPage ){
252 if( g.perm.ApndWiki==0 || g.perm.Attach==0 ){
253 login_needed(g.anon.ApndWiki && g.anon.Attach);
254 return;
@@ -257,10 +289,24 @@
257 fossil_redirect_home();
258 }
259 zTarget = zPage;
260 zTargetType = mprintf("Wiki Page <a href=\"%R/wiki?name=%h\">%h</a>",
261 zPage, zPage);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262 }else{
263 if( g.perm.ApndTkt==0 || g.perm.Attach==0 ){
264 login_needed(g.anon.ApndTkt && g.anon.Attach);
265 return;
266 }
@@ -340,10 +386,12 @@
340 @ <input type="file" name="f" size="60" /><br />
341 @ Description:<br />
342 @ <textarea name="comment" cols="80" rows="5" wrap="virtual"></textarea><br />
343 if( zTkt ){
344 @ <input type="hidden" name="tkt" value="%h(zTkt)" />
 
 
345 }else{
346 @ <input type="hidden" name="page" value="%h(zPage)" />
347 }
348 @ <input type="hidden" name="from" value="%h(zFrom)" />
349 @ <input type="submit" name="ok" value="Add Attachment" />
@@ -350,10 +398,11 @@
350 @ <input type="submit" name="cancel" value="Cancel" />
351 @ </div>
352 captcha_generate(0);
353 @ </form>
354 style_footer();
 
355 }
356
357 /*
358 ** WEBPAGE: ainfo
359 ** URL: /ainfo?name=ARTIFACTID
@@ -364,15 +413,16 @@
364 int rid; /* RID for the control artifact */
365 int ridSrc; /* RID for the attached file */
366 char *zDate; /* Date attached */
367 const char *zUuid; /* UUID of the control artifact */
368 Manifest *pAttach; /* Parse of the control artifact */
369 const char *zTarget; /* Wiki or ticket attached to */
370 const char *zSrc; /* UUID of the attached file */
371 const char *zName; /* Name of the attached file */
372 const char *zDesc; /* Description of the attached file */
373 const char *zWikiName = 0; /* Wiki page name when attached to Wiki */
 
374 const char *zTktUuid = 0; /* Ticket ID when attached to a ticket */
375 int modPending; /* True if awaiting moderation */
376 const char *zModAction; /* Moderation action or NULL */
377 int isModerator; /* TRUE if user is the moderator */
378 const char *zMime; /* MIME Type */
@@ -422,15 +472,23 @@
422 zWikiName = zTarget;
423 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
424 if( g.perm.WrWiki ){
425 style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
426 }
 
 
 
 
 
 
427 }
428 zDate = db_text(0, "SELECT datetime(%.12f)", pAttach->rDate);
429
430 if( P("confirm")
431 && ((zTktUuid && g.perm.WrTkt) || (zWikiName && g.perm.WrWiki))
 
 
432 ){
433 int i, n, rid;
434 char *zDate;
435 Blob manifest;
436 Blob cksum;
@@ -454,11 +512,13 @@
454 db_end_transaction(0);
455 @ <p>The attachment below has been deleted.</p>
456 }
457
458 if( P("del")
459 && ((zTktUuid && g.perm.WrTkt) || (zWikiName && g.perm.WrWiki))
 
 
460 ){
461 form_begin(0, "%R/ainfo/%!S", zUuid);
462 @ <p>Confirm you want to delete the attachment shown below.
463 @ <input type="submit" name="confirm" value="Confirm">
464 @ </form>
@@ -502,10 +562,14 @@
502 }
503 if( zTktUuid ){
504 @ <tr><th>Ticket:</th>
505 @ <td>%z(href("%R/tktview/%s",zTktUuid))%s(zTktUuid)</a></td></tr>
506 }
 
 
 
 
507 if( zWikiName ){
508 @ <tr><th>Wiki&nbsp;Page:</th>
509 @ <td>%z(href("%R/wiki?name=%t",zWikiName))%h(zWikiName)</a></td></tr>
510 }
511 @ <tr><th>Date:</th><td>
512
--- src/attach.c
+++ src/attach.c
@@ -26,28 +26,36 @@
26 ** List attachments.
27 **
28 ** tkt=TICKETUUID
29 ** page=WIKIPAGE
30 **
31 ** At most one of technote=, tkt= or page= are supplied.
32 ** If none is given, all attachments are listed. If one is given,
33 ** only attachments for the designated technote, ticket or wiki page
34 ** are shown. TECHNOTEUUID and TICKETUUID may be just a prefix of the
35 ** relevant tech note or ticket, in which case all attachments of all
36 ** tech notes or tickets with the prefix will be listed.
37 */
38 void attachlist_page(void){
39 const char *zPage = P("page");
40 const char *zTkt = P("tkt");
41 const char *zTechNote = P("technote");
42 Blob sql;
43 Stmt q;
44
45 if( zPage && zTkt ) zTkt = 0;
46 login_check_credentials();
47 blob_zero(&sql);
48 blob_append_sql(&sql,
49 "SELECT datetime(mtime,toLocal()), src, target, filename,"
50 " comment, user,"
51 " (SELECT uuid FROM blob WHERE rid=attachid), attachid,"
52 " (CASE WHEN 'tkt-'||target IN (SELECT tagname FROM tag)"
53 " THEN 1"
54 " WHEN 'event-'||target IN (SELECT tagname FROM tag)"
55 " THEN 2"
56 " ELSE 0 END)"
57 " FROM attachment"
58 );
59 if( zPage ){
60 if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
61 style_header("Attachments To %h", zPage);
@@ -54,10 +62,15 @@
62 blob_append_sql(&sql, " WHERE target=%Q", zPage);
63 }else if( zTkt ){
64 if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
65 style_header("Attachments To Ticket %S", zTkt);
66 blob_append_sql(&sql, " WHERE target GLOB '%q*'", zTkt);
67 }else if( zTechNote ){
68 if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
69 style_header("Attachments to Tech Note %S", zTechNote);
70 blob_append_sql(&sql, " WHERE target GLOB '%q*'",
71 zTechNote);
72 }else{
73 if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ){
74 login_needed(g.anon.RdTkt || g.anon.RdWiki);
75 return;
76 }
@@ -73,21 +86,25 @@
86 const char *zFilename = db_column_text(&q, 3);
87 const char *zComment = db_column_text(&q, 4);
88 const char *zUser = db_column_text(&q, 5);
89 const char *zUuid = db_column_text(&q, 6);
90 int attachid = db_column_int(&q, 7);
91 // type 0 is a wiki page, 1 is a ticket, 2 is a tech note
92 int type = db_column_int(&q, 8);
93 const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
94 int i;
95 char *zUrlTail;
96 for(i=0; zFilename[i]; i++){
97 if( zFilename[i]=='/' && zFilename[i+1]!=0 ){
98 zFilename = &zFilename[i+1];
99 i = -1;
100 }
101 }
102 if( type==1 ){
103 zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
104 }else if( type==2 ){
105 zUrlTail = mprintf("technote=%s&file=%t", zTarget, zFilename);
106 }else{
107 zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
108 }
109 @ <li><p>
110 @ Attachment %z(href("%R/ainfo/%!S",zUuid))%S(zUuid)</a>
@@ -98,19 +115,22 @@
115 @ [<a href="%R/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br />
116 if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++;
117 if( zComment && zComment[0] ){
118 @ %!W(zComment)<br />
119 }
120 if( zPage==0 && zTkt==0 && zTechNote==0 ){
121 if( zSrc==0 || zSrc[0]==0 ){
122 zSrc = "Deleted from";
123 }else {
124 zSrc = "Added to";
125 }
126 if( type==1 ){
127 @ %s(zSrc) ticket <a href="%R/tktview?name=%s(zTarget)">
128 @ %S(zTarget)</a>
129 }else if( type==2 ){
130 @ %s(zSrc) tech note <a href="%R/technote/%s(zTarget)">
131 @ %S(zTarget)</a>
132 }else{
133 @ %s(zSrc) wiki page <a href="%R/wiki?name=%t(zTarget)">
134 @ %h(zTarget)</a>
135 }
136 }else{
@@ -138,31 +158,35 @@
158 ** Download or display an attachment.
159 ** Query parameters:
160 **
161 ** tkt=TICKETUUID
162 ** page=WIKIPAGE
163 ** technote=TECHNOTEUUID
164 ** file=FILENAME
165 ** attachid=ID
166 **
167 */
168 void attachview_page(void){
169 const char *zPage = P("page");
170 const char *zTkt = P("tkt");
171 const char *zTechNote = P("technote");
172 const char *zFile = P("file");
173 const char *zTarget = 0;
174 int attachid = atoi(PD("attachid","0"));
175 char *zUUID;
176
 
177 if( zFile==0 ) fossil_redirect_home();
178 login_check_credentials();
179 if( zPage ){
180 if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
181 zTarget = zPage;
182 }else if( zTkt ){
183 if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
184 zTarget = zTkt;
185 }else if( zTechNote ){
186 if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
187 zTarget = zTechNote;
188 }else{
189 fossil_redirect_home();
190 }
191 if( attachid>0 ){
192 zUUID = db_text(0,
@@ -186,18 +210,19 @@
210 }else if( zUUID[0]=='x' ){
211 style_header("Missing");
212 @ Attachment has been deleted
213 style_footer();
214 return;
 
 
 
 
 
215 }else{
216 g.perm.Read = 1;
217 cgi_replace_parameter("name",zUUID);
218 if( fossil_strcmp(g.zPath,"attachview")==0 ){
219 artifact_page();
220 }else{
221 cgi_replace_parameter("m", mimetype_from_name(zFile));
222 rawartifact_page();
223 }
224 }
225 }
226
227 /*
228 ** Save an attachment control artifact into the repository
@@ -228,27 +253,34 @@
253 ** WEBPAGE: attachadd
254 ** Add a new attachment.
255 **
256 ** tkt=TICKETUUID
257 ** page=WIKIPAGE
258 ** technote=TECHNOTEUUID
259 ** from=URL
260 **
261 */
262 void attachadd_page(void){
263 const char *zPage = P("page");
264 const char *zTkt = P("tkt");
265 const char *zTechNote = P("technote");
266 const char *zFrom = P("from");
267 const char *aContent = P("f");
268 const char *zName = PD("f:filename","unknown");
269 const char *zTarget;
270 char *zTargetType;
271 int szContent = atoi(PD("f:bytes","0"));
272 int goodCaptcha = 1;
273
274 if( P("cancel") ) cgi_redirect(zFrom);
275 if( (zPage && zTkt)
276 || (zPage && zTechNote)
277 || (zTkt && zTechNote)
278 ){
279 fossil_redirect_home();
280 }
281 if( zPage==0 && zTkt==0 && zTechNote==0) fossil_redirect_home();
282 login_check_credentials();
283 if( zPage ){
284 if( g.perm.ApndWiki==0 || g.perm.Attach==0 ){
285 login_needed(g.anon.ApndWiki && g.anon.Attach);
286 return;
@@ -257,10 +289,24 @@
289 fossil_redirect_home();
290 }
291 zTarget = zPage;
292 zTargetType = mprintf("Wiki Page <a href=\"%R/wiki?name=%h\">%h</a>",
293 zPage, zPage);
294 }else if ( zTechNote ){
295 if( g.perm.Write==0 || g.perm.ApndWiki==0 || g.perm.Attach==0 ){
296 login_needed(g.anon.Write && g.anon.ApndWiki && g.anon.Attach);
297 return;
298 }
299 if( !db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'", zTechNote) ){
300 zTechNote = db_text(0, "SELECT substr(tagname,7) FROM tag"
301 " WHERE tagname GLOB 'event-%q*'", zTechNote);
302 if( zTechNote==0) fossil_redirect_home();
303 }
304 zTarget = zTechNote;
305 zTargetType = mprintf("Tech Note <a href=\"%R/technote/%h\">%h</a>",
306 zTechNote, zTechNote);
307
308 }else{
309 if( g.perm.ApndTkt==0 || g.perm.Attach==0 ){
310 login_needed(g.anon.ApndTkt && g.anon.Attach);
311 return;
312 }
@@ -340,10 +386,12 @@
386 @ <input type="file" name="f" size="60" /><br />
387 @ Description:<br />
388 @ <textarea name="comment" cols="80" rows="5" wrap="virtual"></textarea><br />
389 if( zTkt ){
390 @ <input type="hidden" name="tkt" value="%h(zTkt)" />
391 }else if( zTechNote ){
392 @ <input type="hidden" name="technote" value="%h(zTechNote)" />
393 }else{
394 @ <input type="hidden" name="page" value="%h(zPage)" />
395 }
396 @ <input type="hidden" name="from" value="%h(zFrom)" />
397 @ <input type="submit" name="ok" value="Add Attachment" />
@@ -350,10 +398,11 @@
398 @ <input type="submit" name="cancel" value="Cancel" />
399 @ </div>
400 captcha_generate(0);
401 @ </form>
402 style_footer();
403 fossil_free(zTargetType);
404 }
405
406 /*
407 ** WEBPAGE: ainfo
408 ** URL: /ainfo?name=ARTIFACTID
@@ -364,15 +413,16 @@
413 int rid; /* RID for the control artifact */
414 int ridSrc; /* RID for the attached file */
415 char *zDate; /* Date attached */
416 const char *zUuid; /* UUID of the control artifact */
417 Manifest *pAttach; /* Parse of the control artifact */
418 const char *zTarget; /* Wiki, ticket or tech note attached to */
419 const char *zSrc; /* UUID of the attached file */
420 const char *zName; /* Name of the attached file */
421 const char *zDesc; /* Description of the attached file */
422 const char *zWikiName = 0; /* Wiki page name when attached to Wiki */
423 const char *zTNUuid = 0; /* Tech Note ID when attached to tech note */
424 const char *zTktUuid = 0; /* Ticket ID when attached to a ticket */
425 int modPending; /* True if awaiting moderation */
426 const char *zModAction; /* Moderation action or NULL */
427 int isModerator; /* TRUE if user is the moderator */
428 const char *zMime; /* MIME Type */
@@ -422,15 +472,23 @@
472 zWikiName = zTarget;
473 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
474 if( g.perm.WrWiki ){
475 style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
476 }
477 }else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",zTarget) ){
478 zTNUuid = zTarget;
479 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
480 if( g.perm.Write && g.perm.WrWiki ){
481 style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
482 }
483 }
484 zDate = db_text(0, "SELECT datetime(%.12f)", pAttach->rDate);
485
486 if( P("confirm")
487 && ((zTktUuid && g.perm.WrTkt) ||
488 (zWikiName && g.perm.WrWiki) ||
489 (zTNUuid && g.perm.Write && g.perm.WrWiki))
490 ){
491 int i, n, rid;
492 char *zDate;
493 Blob manifest;
494 Blob cksum;
@@ -454,11 +512,13 @@
512 db_end_transaction(0);
513 @ <p>The attachment below has been deleted.</p>
514 }
515
516 if( P("del")
517 && ((zTktUuid && g.perm.WrTkt) ||
518 (zWikiName && g.perm.WrWiki) ||
519 (zTNUuid && g.perm.Write && g.perm.WrWiki))
520 ){
521 form_begin(0, "%R/ainfo/%!S", zUuid);
522 @ <p>Confirm you want to delete the attachment shown below.
523 @ <input type="submit" name="confirm" value="Confirm">
524 @ </form>
@@ -502,10 +562,14 @@
562 }
563 if( zTktUuid ){
564 @ <tr><th>Ticket:</th>
565 @ <td>%z(href("%R/tktview/%s",zTktUuid))%s(zTktUuid)</a></td></tr>
566 }
567 if( zTNUuid ){
568 @ <tr><th>Tech Note:</th>
569 @ <td>%z(href("%R/technote/%s",zTNUuid))%s(zTNUuid)</a></td></tr>
570 }
571 if( zWikiName ){
572 @ <tr><th>Wiki&nbsp;Page:</th>
573 @ <td>%z(href("%R/wiki?name=%t",zWikiName))%h(zWikiName)</a></td></tr>
574 }
575 @ <tr><th>Date:</th><td>
576
+88 -36
--- src/delta.c
+++ src/delta.c
@@ -102,16 +102,16 @@
102102
/*
103103
** Initialize the rolling hash using the first NHASH characters of z[]
104104
*/
105105
static void hash_init(hash *pHash, const char *z){
106106
u16 a, b, i;
107
- a = b = 0;
108
- for(i=0; i<NHASH; i++){
107
+ a = b = z[0];
108
+ for(i=1; i<NHASH; i++){
109109
a += z[i];
110
- b += (NHASH-i)*z[i];
111
- pHash->z[i] = z[i];
110
+ b += a;
112111
}
112
+ memcpy(pHash->z, z, NHASH);
113113
pHash->a = a & 0xffff;
114114
pHash->b = b & 0xffff;
115115
pHash->i = 0;
116116
}
117117
@@ -130,10 +130,28 @@
130130
** Return a 32-bit hash value
131131
*/
132132
static u32 hash_32bit(hash *pHash){
133133
return (pHash->a & 0xffff) | (((u32)(pHash->b & 0xffff))<<16);
134134
}
135
+
136
+/*
137
+** Compute a hash on NHASH bytes.
138
+**
139
+** This routine is intended to be equivalent to:
140
+** hash h;
141
+** hash_init(&h, zInput);
142
+** return hash_32bit(&h);
143
+*/
144
+static u32 hash_once(const char *z){
145
+ u16 a, b, i;
146
+ a = b = z[0];
147
+ for(i=1; i<NHASH; i++){
148
+ a += z[i];
149
+ b += a;
150
+ }
151
+ return a | (((u32)b)<<16);
152
+}
135153
136154
/*
137155
** Write an base-64 integer into the given buffer.
138156
*/
139157
static void putInt(unsigned int v, char **pz){
@@ -191,43 +209,76 @@
191209
unsigned int i, x;
192210
for(i=1, x=64; v>=x; i++, x <<= 6){}
193211
return i;
194212
}
195213
214
+#ifdef __GNUC__
215
+# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
216
+#else
217
+# define GCC_VERSION 0
218
+#endif
219
+
196220
/*
197
-** Compute a 32-bit checksum on the N-byte buffer. Return the result.
221
+** Compute a 32-bit big-endian checksum on the N-byte buffer. If the
222
+** buffer is not a multiple of 4 bytes length, compute the sum that would
223
+** have occurred if the buffer was padded with zeros to the next multiple
224
+** of four bytes.
198225
*/
199226
static unsigned int checksum(const char *zIn, size_t N){
227
+ static const int byteOrderTest = 1;
200228
const unsigned char *z = (const unsigned char *)zIn;
201
- unsigned sum0 = 0;
202
- unsigned sum1 = 0;
203
- unsigned sum2 = 0;
204
- unsigned sum3 = 0;
205
- while(N >= 16){
206
- sum0 += ((unsigned)z[0] + z[4] + z[8] + z[12]);
207
- sum1 += ((unsigned)z[1] + z[5] + z[9] + z[13]);
208
- sum2 += ((unsigned)z[2] + z[6] + z[10]+ z[14]);
209
- sum3 += ((unsigned)z[3] + z[7] + z[11]+ z[15]);
210
- z += 16;
211
- N -= 16;
212
- }
213
- while(N >= 4){
214
- sum0 += z[0];
215
- sum1 += z[1];
216
- sum2 += z[2];
217
- sum3 += z[3];
218
- z += 4;
219
- N -= 4;
220
- }
221
- sum3 += (sum2 << 8) + (sum1 << 16) + (sum0 << 24);
222
- switch(N){
223
- case 3: sum3 += (z[2] << 8);
224
- case 2: sum3 += (z[1] << 16);
225
- case 1: sum3 += (z[0] << 24);
229
+ const unsigned char *zEnd = (const unsigned char*)&zIn[N&~3];
230
+ unsigned sum = 0;
231
+ assert( (z - (const unsigned char*)0)%4==0 ); /* Four-byte alignment */
232
+ if( 0==*(char*)&byteOrderTest ){
233
+ /* This is a big-endian machine */
234
+ while( z<zEnd ){
235
+ sum += *(unsigned*)z;
236
+ z += 4;
237
+ }
238
+ }else{
239
+ /* A little-endian machine */
240
+#if GCC_VERSION>=4003000
241
+ while( z<zEnd ){
242
+ sum += __builtin_bswap32(*(unsigned*)z);
243
+ z += 4;
244
+ }
245
+#elif defined(_MSC_VER) && _MSC_VER>=1300
246
+ while( z<zEnd ){
247
+ sum += _byteswap_ulong(*(unsigned*)z);
248
+ z += 4;
249
+ }
250
+#else
251
+ unsigned sum0 = 0;
252
+ unsigned sum1 = 0;
253
+ unsigned sum2 = 0;
254
+ while(N >= 16){
255
+ sum0 += ((unsigned)z[0] + z[4] + z[8] + z[12]);
256
+ sum1 += ((unsigned)z[1] + z[5] + z[9] + z[13]);
257
+ sum2 += ((unsigned)z[2] + z[6] + z[10]+ z[14]);
258
+ sum += ((unsigned)z[3] + z[7] + z[11]+ z[15]);
259
+ z += 16;
260
+ N -= 16;
261
+ }
262
+ while(N >= 4){
263
+ sum0 += z[0];
264
+ sum1 += z[1];
265
+ sum2 += z[2];
266
+ sum += z[3];
267
+ z += 4;
268
+ N -= 4;
269
+ }
270
+ sum += (sum2 << 8) + (sum1 << 16) + (sum0 << 24);
271
+#endif
272
+ }
273
+ switch(N&3){
274
+ case 3: sum += (z[2] << 8);
275
+ case 2: sum += (z[1] << 16);
276
+ case 1: sum += (z[0] << 24);
226277
default: ;
227278
}
228
- return sum3;
279
+ return sum;
229280
}
230281
231282
/*
232283
** Create a new delta.
233284
**
@@ -330,13 +381,11 @@
330381
collide = fossil_malloc( nHash*2*sizeof(int) );
331382
landmark = &collide[nHash];
332383
memset(landmark, -1, nHash*sizeof(int));
333384
memset(collide, -1, nHash*sizeof(int));
334385
for(i=0; i<lenSrc-NHASH; i+=NHASH){
335
- int hv;
336
- hash_init(&h, &zSrc[i]);
337
- hv = hash_32bit(&h) % nHash;
386
+ int hv = hash_once(&zSrc[i]) % nHash;
338387
collide[i/NHASH] = landmark[hv];
339388
landmark[hv] = i/NHASH;
340389
}
341390
342391
/* Begin scanning the target file and generating copy commands and
@@ -373,18 +422,21 @@
373422
** copy command is less than the amount of literal text to be copied.
374423
*/
375424
int cnt, ofst, litsz;
376425
int j, k, x, y;
377426
int sz;
427
+ int limitX;
378428
379429
/* Beginning at iSrc, match forwards as far as we can. j counts
380430
** the number of characters that match */
381431
iSrc = iBlock*NHASH;
382
- for(j=0, x=iSrc, y=base+i; x<lenSrc && y<lenOut; j++, x++, y++){
432
+ y = base+i;
433
+ limitX = ( lenSrc-iSrc <= lenOut-y ) ? lenSrc : iSrc + lenOut - y;
434
+ for(x=iSrc; x<limitX; x++, y++){
383435
if( zSrc[x]!=zOut[y] ) break;
384436
}
385
- j--;
437
+ j = x - iSrc - 1;
386438
387439
/* Beginning at iSrc-1, match backwards as far as we can. k counts
388440
** the number of characters that match */
389441
for(k=1; k<iSrc && k<=i; k++){
390442
if( zSrc[iSrc-k]!=zOut[base+i-k] ) break;
391443
--- src/delta.c
+++ src/delta.c
@@ -102,16 +102,16 @@
102 /*
103 ** Initialize the rolling hash using the first NHASH characters of z[]
104 */
105 static void hash_init(hash *pHash, const char *z){
106 u16 a, b, i;
107 a = b = 0;
108 for(i=0; i<NHASH; i++){
109 a += z[i];
110 b += (NHASH-i)*z[i];
111 pHash->z[i] = z[i];
112 }
 
113 pHash->a = a & 0xffff;
114 pHash->b = b & 0xffff;
115 pHash->i = 0;
116 }
117
@@ -130,10 +130,28 @@
130 ** Return a 32-bit hash value
131 */
132 static u32 hash_32bit(hash *pHash){
133 return (pHash->a & 0xffff) | (((u32)(pHash->b & 0xffff))<<16);
134 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
136 /*
137 ** Write an base-64 integer into the given buffer.
138 */
139 static void putInt(unsigned int v, char **pz){
@@ -191,43 +209,76 @@
191 unsigned int i, x;
192 for(i=1, x=64; v>=x; i++, x <<= 6){}
193 return i;
194 }
195
 
 
 
 
 
 
196 /*
197 ** Compute a 32-bit checksum on the N-byte buffer. Return the result.
 
 
 
198 */
199 static unsigned int checksum(const char *zIn, size_t N){
 
200 const unsigned char *z = (const unsigned char *)zIn;
201 unsigned sum0 = 0;
202 unsigned sum1 = 0;
203 unsigned sum2 = 0;
204 unsigned sum3 = 0;
205 while(N >= 16){
206 sum0 += ((unsigned)z[0] + z[4] + z[8] + z[12]);
207 sum1 += ((unsigned)z[1] + z[5] + z[9] + z[13]);
208 sum2 += ((unsigned)z[2] + z[6] + z[10]+ z[14]);
209 sum3 += ((unsigned)z[3] + z[7] + z[11]+ z[15]);
210 z += 16;
211 N -= 16;
212 }
213 while(N >= 4){
214 sum0 += z[0];
215 sum1 += z[1];
216 sum2 += z[2];
217 sum3 += z[3];
218 z += 4;
219 N -= 4;
220 }
221 sum3 += (sum2 << 8) + (sum1 << 16) + (sum0 << 24);
222 switch(N){
223 case 3: sum3 += (z[2] << 8);
224 case 2: sum3 += (z[1] << 16);
225 case 1: sum3 += (z[0] << 24);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226 default: ;
227 }
228 return sum3;
229 }
230
231 /*
232 ** Create a new delta.
233 **
@@ -330,13 +381,11 @@
330 collide = fossil_malloc( nHash*2*sizeof(int) );
331 landmark = &collide[nHash];
332 memset(landmark, -1, nHash*sizeof(int));
333 memset(collide, -1, nHash*sizeof(int));
334 for(i=0; i<lenSrc-NHASH; i+=NHASH){
335 int hv;
336 hash_init(&h, &zSrc[i]);
337 hv = hash_32bit(&h) % nHash;
338 collide[i/NHASH] = landmark[hv];
339 landmark[hv] = i/NHASH;
340 }
341
342 /* Begin scanning the target file and generating copy commands and
@@ -373,18 +422,21 @@
373 ** copy command is less than the amount of literal text to be copied.
374 */
375 int cnt, ofst, litsz;
376 int j, k, x, y;
377 int sz;
 
378
379 /* Beginning at iSrc, match forwards as far as we can. j counts
380 ** the number of characters that match */
381 iSrc = iBlock*NHASH;
382 for(j=0, x=iSrc, y=base+i; x<lenSrc && y<lenOut; j++, x++, y++){
 
 
383 if( zSrc[x]!=zOut[y] ) break;
384 }
385 j--;
386
387 /* Beginning at iSrc-1, match backwards as far as we can. k counts
388 ** the number of characters that match */
389 for(k=1; k<iSrc && k<=i; k++){
390 if( zSrc[iSrc-k]!=zOut[base+i-k] ) break;
391
--- src/delta.c
+++ src/delta.c
@@ -102,16 +102,16 @@
102 /*
103 ** Initialize the rolling hash using the first NHASH characters of z[]
104 */
105 static void hash_init(hash *pHash, const char *z){
106 u16 a, b, i;
107 a = b = z[0];
108 for(i=1; i<NHASH; i++){
109 a += z[i];
110 b += a;
 
111 }
112 memcpy(pHash->z, z, NHASH);
113 pHash->a = a & 0xffff;
114 pHash->b = b & 0xffff;
115 pHash->i = 0;
116 }
117
@@ -130,10 +130,28 @@
130 ** Return a 32-bit hash value
131 */
132 static u32 hash_32bit(hash *pHash){
133 return (pHash->a & 0xffff) | (((u32)(pHash->b & 0xffff))<<16);
134 }
135
136 /*
137 ** Compute a hash on NHASH bytes.
138 **
139 ** This routine is intended to be equivalent to:
140 ** hash h;
141 ** hash_init(&h, zInput);
142 ** return hash_32bit(&h);
143 */
144 static u32 hash_once(const char *z){
145 u16 a, b, i;
146 a = b = z[0];
147 for(i=1; i<NHASH; i++){
148 a += z[i];
149 b += a;
150 }
151 return a | (((u32)b)<<16);
152 }
153
154 /*
155 ** Write an base-64 integer into the given buffer.
156 */
157 static void putInt(unsigned int v, char **pz){
@@ -191,43 +209,76 @@
209 unsigned int i, x;
210 for(i=1, x=64; v>=x; i++, x <<= 6){}
211 return i;
212 }
213
214 #ifdef __GNUC__
215 # define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
216 #else
217 # define GCC_VERSION 0
218 #endif
219
220 /*
221 ** Compute a 32-bit big-endian checksum on the N-byte buffer. If the
222 ** buffer is not a multiple of 4 bytes length, compute the sum that would
223 ** have occurred if the buffer was padded with zeros to the next multiple
224 ** of four bytes.
225 */
226 static unsigned int checksum(const char *zIn, size_t N){
227 static const int byteOrderTest = 1;
228 const unsigned char *z = (const unsigned char *)zIn;
229 const unsigned char *zEnd = (const unsigned char*)&zIn[N&~3];
230 unsigned sum = 0;
231 assert( (z - (const unsigned char*)0)%4==0 ); /* Four-byte alignment */
232 if( 0==*(char*)&byteOrderTest ){
233 /* This is a big-endian machine */
234 while( z<zEnd ){
235 sum += *(unsigned*)z;
236 z += 4;
237 }
238 }else{
239 /* A little-endian machine */
240 #if GCC_VERSION>=4003000
241 while( z<zEnd ){
242 sum += __builtin_bswap32(*(unsigned*)z);
243 z += 4;
244 }
245 #elif defined(_MSC_VER) && _MSC_VER>=1300
246 while( z<zEnd ){
247 sum += _byteswap_ulong(*(unsigned*)z);
248 z += 4;
249 }
250 #else
251 unsigned sum0 = 0;
252 unsigned sum1 = 0;
253 unsigned sum2 = 0;
254 while(N >= 16){
255 sum0 += ((unsigned)z[0] + z[4] + z[8] + z[12]);
256 sum1 += ((unsigned)z[1] + z[5] + z[9] + z[13]);
257 sum2 += ((unsigned)z[2] + z[6] + z[10]+ z[14]);
258 sum += ((unsigned)z[3] + z[7] + z[11]+ z[15]);
259 z += 16;
260 N -= 16;
261 }
262 while(N >= 4){
263 sum0 += z[0];
264 sum1 += z[1];
265 sum2 += z[2];
266 sum += z[3];
267 z += 4;
268 N -= 4;
269 }
270 sum += (sum2 << 8) + (sum1 << 16) + (sum0 << 24);
271 #endif
272 }
273 switch(N&3){
274 case 3: sum += (z[2] << 8);
275 case 2: sum += (z[1] << 16);
276 case 1: sum += (z[0] << 24);
277 default: ;
278 }
279 return sum;
280 }
281
282 /*
283 ** Create a new delta.
284 **
@@ -330,13 +381,11 @@
381 collide = fossil_malloc( nHash*2*sizeof(int) );
382 landmark = &collide[nHash];
383 memset(landmark, -1, nHash*sizeof(int));
384 memset(collide, -1, nHash*sizeof(int));
385 for(i=0; i<lenSrc-NHASH; i+=NHASH){
386 int hv = hash_once(&zSrc[i]) % nHash;
 
 
387 collide[i/NHASH] = landmark[hv];
388 landmark[hv] = i/NHASH;
389 }
390
391 /* Begin scanning the target file and generating copy commands and
@@ -373,18 +422,21 @@
422 ** copy command is less than the amount of literal text to be copied.
423 */
424 int cnt, ofst, litsz;
425 int j, k, x, y;
426 int sz;
427 int limitX;
428
429 /* Beginning at iSrc, match forwards as far as we can. j counts
430 ** the number of characters that match */
431 iSrc = iBlock*NHASH;
432 y = base+i;
433 limitX = ( lenSrc-iSrc <= lenOut-y ) ? lenSrc : iSrc + lenOut - y;
434 for(x=iSrc; x<limitX; x++, y++){
435 if( zSrc[x]!=zOut[y] ) break;
436 }
437 j = x - iSrc - 1;
438
439 /* Beginning at iSrc-1, match backwards as far as we can. k counts
440 ** the number of characters that match */
441 for(k=1; k<iSrc && k<=i; k++){
442 if( zSrc[iSrc-k]!=zOut[base+i-k] ) break;
443
+3 -1
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -80,11 +80,11 @@
8080
*/
8181
void delta_analyze_cmd(void){
8282
Blob orig, target, delta;
8383
int nCopy = 0;
8484
int nInsert = 0;
85
- int sz1, sz2;
85
+ int sz1, sz2, sz3;
8686
if( g.argc!=4 ){
8787
usage("ORIGIN TARGET");
8888
}
8989
if( blob_read_from_file(&orig, g.argv[2])<0 ){
9090
fossil_fatal("cannot read %s\n", g.argv[2]);
@@ -94,19 +94,21 @@
9494
}
9595
blob_delta_create(&orig, &target, &delta);
9696
delta_analyze(blob_buffer(&delta), blob_size(&delta), &nCopy, &nInsert);
9797
sz1 = blob_size(&orig);
9898
sz2 = blob_size(&target);
99
+ sz3 = blob_size(&delta);
99100
blob_reset(&orig);
100101
blob_reset(&target);
101102
blob_reset(&delta);
102103
fossil_print("original size: %8d\n", sz1);
103104
fossil_print("bytes copied: %8d (%.1f%% of target)\n",
104105
nCopy, (100.0*nCopy)/sz2);
105106
fossil_print("bytes inserted: %8d (%.1f%% of target)\n",
106107
nInsert, (100.0*nInsert)/sz2);
107108
fossil_print("final size: %8d\n", sz2);
109
+ fossil_print("delta size: %8d\n", sz3);
108110
}
109111
110112
/*
111113
** Apply the delta in pDelta to the original file pOriginal to generate
112114
** the target file pTarget. The pTarget blob is initialized by this
113115
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -80,11 +80,11 @@
80 */
81 void delta_analyze_cmd(void){
82 Blob orig, target, delta;
83 int nCopy = 0;
84 int nInsert = 0;
85 int sz1, sz2;
86 if( g.argc!=4 ){
87 usage("ORIGIN TARGET");
88 }
89 if( blob_read_from_file(&orig, g.argv[2])<0 ){
90 fossil_fatal("cannot read %s\n", g.argv[2]);
@@ -94,19 +94,21 @@
94 }
95 blob_delta_create(&orig, &target, &delta);
96 delta_analyze(blob_buffer(&delta), blob_size(&delta), &nCopy, &nInsert);
97 sz1 = blob_size(&orig);
98 sz2 = blob_size(&target);
 
99 blob_reset(&orig);
100 blob_reset(&target);
101 blob_reset(&delta);
102 fossil_print("original size: %8d\n", sz1);
103 fossil_print("bytes copied: %8d (%.1f%% of target)\n",
104 nCopy, (100.0*nCopy)/sz2);
105 fossil_print("bytes inserted: %8d (%.1f%% of target)\n",
106 nInsert, (100.0*nInsert)/sz2);
107 fossil_print("final size: %8d\n", sz2);
 
108 }
109
110 /*
111 ** Apply the delta in pDelta to the original file pOriginal to generate
112 ** the target file pTarget. The pTarget blob is initialized by this
113
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -80,11 +80,11 @@
80 */
81 void delta_analyze_cmd(void){
82 Blob orig, target, delta;
83 int nCopy = 0;
84 int nInsert = 0;
85 int sz1, sz2, sz3;
86 if( g.argc!=4 ){
87 usage("ORIGIN TARGET");
88 }
89 if( blob_read_from_file(&orig, g.argv[2])<0 ){
90 fossil_fatal("cannot read %s\n", g.argv[2]);
@@ -94,19 +94,21 @@
94 }
95 blob_delta_create(&orig, &target, &delta);
96 delta_analyze(blob_buffer(&delta), blob_size(&delta), &nCopy, &nInsert);
97 sz1 = blob_size(&orig);
98 sz2 = blob_size(&target);
99 sz3 = blob_size(&delta);
100 blob_reset(&orig);
101 blob_reset(&target);
102 blob_reset(&delta);
103 fossil_print("original size: %8d\n", sz1);
104 fossil_print("bytes copied: %8d (%.1f%% of target)\n",
105 nCopy, (100.0*nCopy)/sz2);
106 fossil_print("bytes inserted: %8d (%.1f%% of target)\n",
107 nInsert, (100.0*nInsert)/sz2);
108 fossil_print("final size: %8d\n", sz2);
109 fossil_print("delta size: %8d\n", sz3);
110 }
111
112 /*
113 ** Apply the delta in pDelta to the original file pOriginal to generate
114 ** the target file pTarget. The pTarget blob is initialized by this
115
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -74,11 +74,10 @@
7474
** a file in a directory named on the azInclude[] list.
7575
**
7676
** if azInclude is NULL, then always include zFile.
7777
*/
7878
static int file_dir_match(FileDirList *p, const char *zFile){
79
- int i = 0;
8079
if( p==0 || strcmp(p->zName,".")==0 ) return 1;
8180
if( filenames_are_case_sensitive() ){
8281
while( p->zName ){
8382
if( strcmp(zFile, p->zName)==0
8483
|| (strncmp(zFile, p->zName, p->nName)==0
8584
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -74,11 +74,10 @@
74 ** a file in a directory named on the azInclude[] list.
75 **
76 ** if azInclude is NULL, then always include zFile.
77 */
78 static int file_dir_match(FileDirList *p, const char *zFile){
79 int i = 0;
80 if( p==0 || strcmp(p->zName,".")==0 ) return 1;
81 if( filenames_are_case_sensitive() ){
82 while( p->zName ){
83 if( strcmp(zFile, p->zName)==0
84 || (strncmp(zFile, p->zName, p->nName)==0
85
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -74,11 +74,10 @@
74 ** a file in a directory named on the azInclude[] list.
75 **
76 ** if azInclude is NULL, then always include zFile.
77 */
78 static int file_dir_match(FileDirList *p, const char *zFile){
 
79 if( p==0 || strcmp(p->zName,".")==0 ) return 1;
80 if( filenames_are_case_sensitive() ){
81 while( p->zName ){
82 if( strcmp(zFile, p->zName)==0
83 || (strncmp(zFile, p->zName, p->nName)==0
84
+2
--- src/doc.c
+++ src/doc.c
@@ -93,10 +93,11 @@
9393
{ "class", 5, "application/octet-stream" },
9494
{ "cod", 3, "application/vnd.rim.cod" },
9595
{ "com", 3, "application/x-msdos-program" },
9696
{ "cpio", 4, "application/x-cpio" },
9797
{ "cpt", 3, "application/mac-compactpro" },
98
+ { "cs", 2, "text/plain" },
9899
{ "csh", 3, "application/x-csh" },
99100
{ "css", 3, "text/css" },
100101
{ "csv", 3, "text/csv" },
101102
{ "dcr", 3, "application/x-director" },
102103
{ "deb", 3, "application/x-debian-package" },
@@ -255,10 +256,11 @@
255256
{ "tsp", 3, "application/dsptype" },
256257
{ "tsv", 3, "text/tab-separated-values" },
257258
{ "txt", 3, "text/plain" },
258259
{ "unv", 3, "application/i-deas" },
259260
{ "ustar", 5, "application/x-ustar" },
261
+ { "vb", 2, "text/plain" },
260262
{ "vcd", 3, "application/x-cdlink" },
261263
{ "vda", 3, "application/vda" },
262264
{ "viv", 3, "video/vnd.vivo" },
263265
{ "vivo", 4, "video/vnd.vivo" },
264266
{ "vrml", 4, "model/vrml" },
265267
--- src/doc.c
+++ src/doc.c
@@ -93,10 +93,11 @@
93 { "class", 5, "application/octet-stream" },
94 { "cod", 3, "application/vnd.rim.cod" },
95 { "com", 3, "application/x-msdos-program" },
96 { "cpio", 4, "application/x-cpio" },
97 { "cpt", 3, "application/mac-compactpro" },
 
98 { "csh", 3, "application/x-csh" },
99 { "css", 3, "text/css" },
100 { "csv", 3, "text/csv" },
101 { "dcr", 3, "application/x-director" },
102 { "deb", 3, "application/x-debian-package" },
@@ -255,10 +256,11 @@
255 { "tsp", 3, "application/dsptype" },
256 { "tsv", 3, "text/tab-separated-values" },
257 { "txt", 3, "text/plain" },
258 { "unv", 3, "application/i-deas" },
259 { "ustar", 5, "application/x-ustar" },
 
260 { "vcd", 3, "application/x-cdlink" },
261 { "vda", 3, "application/vda" },
262 { "viv", 3, "video/vnd.vivo" },
263 { "vivo", 4, "video/vnd.vivo" },
264 { "vrml", 4, "model/vrml" },
265
--- src/doc.c
+++ src/doc.c
@@ -93,10 +93,11 @@
93 { "class", 5, "application/octet-stream" },
94 { "cod", 3, "application/vnd.rim.cod" },
95 { "com", 3, "application/x-msdos-program" },
96 { "cpio", 4, "application/x-cpio" },
97 { "cpt", 3, "application/mac-compactpro" },
98 { "cs", 2, "text/plain" },
99 { "csh", 3, "application/x-csh" },
100 { "css", 3, "text/css" },
101 { "csv", 3, "text/csv" },
102 { "dcr", 3, "application/x-director" },
103 { "deb", 3, "application/x-debian-package" },
@@ -255,10 +256,11 @@
256 { "tsp", 3, "application/dsptype" },
257 { "tsv", 3, "text/tab-separated-values" },
258 { "txt", 3, "text/plain" },
259 { "unv", 3, "application/i-deas" },
260 { "ustar", 5, "application/x-ustar" },
261 { "vb", 2, "text/plain" },
262 { "vcd", 3, "application/x-cdlink" },
263 { "vda", 3, "application/vda" },
264 { "viv", 3, "video/vnd.vivo" },
265 { "vivo", 4, "video/vnd.vivo" },
266 { "vrml", 4, "model/vrml" },
267
+176 -82
--- src/event.c
+++ src/event.c
@@ -62,11 +62,11 @@
6262
** Display an existing event identified by EVENTID
6363
*/
6464
void event_page(void){
6565
int rid = 0; /* rid of the event artifact */
6666
char *zUuid; /* UUID corresponding to rid */
67
- const char *zId; /* Event identifier */
67
+ const char *zId; /* Event identifier */
6868
const char *zVerbose; /* Value of verbose option */
6969
char *zETime; /* Time of the tech-note */
7070
char *zATime; /* Time the artifact was created */
7171
int specRid; /* rid specified by aid= parameter */
7272
int prevRid, nextRid; /* Previous or next edits of this tech-note */
@@ -75,10 +75,11 @@
7575
Blob title; /* Title extracted from the technote body */
7676
Blob tail; /* Event body that comes after the title */
7777
Stmt q1; /* Query to search for the technote */
7878
int verboseFlag; /* True to show details */
7979
const char *zMimetype = 0; /* Mimetype of the document */
80
+ const char *zFullId; /* Full event identifier */
8081
8182
8283
/* wiki-read privilege is needed in order to read tech-notes.
8384
*/
8485
login_check_credentials();
@@ -150,10 +151,15 @@
150151
tail = fullbody;
151152
}
152153
style_header("%s", blob_str(&title));
153154
if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){
154155
style_submenu_element("Edit", 0, "%R/technoteedit?name=%!S", zId);
156
+ if( g.perm.Attach ){
157
+ style_submenu_element("Attach", "Add an attachment",
158
+ "%R/attachadd?technote=%!S&from=%R/technote/%!S",
159
+ zId, zId);
160
+ }
155161
}
156162
zETime = db_text(0, "SELECT datetime(%.17g)", pTNote->rEventDate);
157163
style_submenu_element("Context", 0, "%R/timeline?c=%.20s", zId);
158164
if( g.perm.Hyperlink ){
159165
if( verboseFlag ){
@@ -216,13 +222,123 @@
216222
}else{
217223
@ <pre>
218224
@ %h(blob_str(&fullbody))
219225
@ </pre>
220226
}
227
+ zFullId = db_text(0, "SELECT SUBSTR(tagname,7)"
228
+ " FROM tag"
229
+ " WHERE tagname GLOB 'event-%q*'",
230
+ zId);
231
+ attachment_list(zFullId, "<hr /><h2>Attachments:</h2><ul>");
221232
style_footer();
222233
manifest_destroy(pTNote);
223234
}
235
+
236
+/*
237
+** Add or update a new tech note to the repository. rid is id of
238
+** the prior version of this technote, if any.
239
+**
240
+** returns 1 if the tech note was added or updated, 0 if the
241
+** update failed making an invalid artifact
242
+*/
243
+int event_commit_common(
244
+ int rid, /* id of the prior version of the technote */
245
+ const char *zId, /* hash label for the technote */
246
+ const char *zBody, /* content of the technote */
247
+ char *zETime, /* timestamp for the technote */
248
+ const char *zMimetype, /* mimetype for the technote N-card */
249
+ const char *zComment, /* comment shown on the timeline */
250
+ const char *zTags, /* tags associated with this technote */
251
+ const char *zClr /* Background color */
252
+){
253
+ Blob event;
254
+ char *zDate;
255
+ Blob cksum;
256
+ int nrid, n;
257
+
258
+ blob_init(&event, 0, 0);
259
+ db_begin_transaction();
260
+ while( fossil_isspace(zComment[0]) ) zComment++;
261
+ n = strlen(zComment);
262
+ while( n>0 && fossil_isspace(zComment[n-1]) ){ n--; }
263
+ if( n>0 ){
264
+ blob_appendf(&event, "C %#F\n", n, zComment);
265
+ }
266
+ zDate = date_in_standard_format("now");
267
+ blob_appendf(&event, "D %s\n", zDate);
268
+ free(zDate);
269
+
270
+ zETime[10] = 'T';
271
+ blob_appendf(&event, "E %s %s\n", zETime, zId);
272
+ zETime[10] = ' ';
273
+ if( rid ){
274
+ char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
275
+ blob_appendf(&event, "P %s\n", zUuid);
276
+ free(zUuid);
277
+ }
278
+ if( zMimetype && zMimetype[0] ){
279
+ blob_appendf(&event, "N %s\n", zMimetype);
280
+ }
281
+ if( zClr && zClr[0] ){
282
+ blob_appendf(&event, "T +bgcolor * %F\n", zClr);
283
+ }
284
+ if( zTags && zTags[0] ){
285
+ Blob tags, one;
286
+ int i, j;
287
+ Stmt q;
288
+ char *zBlob;
289
+
290
+ /* Load the tags string into a blob */
291
+ blob_zero(&tags);
292
+ blob_append(&tags, zTags, -1);
293
+
294
+ /* Collapse all sequences of whitespace and "," characters into
295
+ ** a single space character */
296
+ zBlob = blob_str(&tags);
297
+ for(i=j=0; zBlob[i]; i++, j++){
298
+ if( fossil_isspace(zBlob[i]) || zBlob[i]==',' ){
299
+ while( fossil_isspace(zBlob[i+1]) ){ i++; }
300
+ zBlob[j] = ' ';
301
+ }else{
302
+ zBlob[j] = zBlob[i];
303
+ }
304
+ }
305
+ blob_resize(&tags, j);
306
+
307
+ /* Parse out each tag and load it into a temporary table for sorting */
308
+ db_multi_exec("CREATE TEMP TABLE newtags(x);");
309
+ while( blob_token(&tags, &one) ){
310
+ db_multi_exec("INSERT INTO newtags VALUES(%B)", &one);
311
+ }
312
+ blob_reset(&tags);
313
+
314
+ /* Extract the tags in sorted order and make an entry in the
315
+ ** artifact for each. */
316
+ db_prepare(&q, "SELECT x FROM newtags ORDER BY x");
317
+ while( db_step(&q)==SQLITE_ROW ){
318
+ blob_appendf(&event, "T +sym-%F *\n", db_column_text(&q, 0));
319
+ }
320
+ db_finalize(&q);
321
+ }
322
+ if( !login_is_nobody() ){
323
+ blob_appendf(&event, "U %F\n", login_name());
324
+ }
325
+ blob_appendf(&event, "W %d\n%s\n", strlen(zBody), zBody);
326
+ md5sum_blob(&event, &cksum);
327
+ blob_appendf(&event, "Z %b\n", &cksum);
328
+ blob_reset(&cksum);
329
+ nrid = content_put(&event);
330
+ db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
331
+ if( manifest_crosslink(nrid, &event, MC_NONE)==0 ){
332
+ db_end_transaction(1);
333
+ return 0;
334
+ }
335
+ assert( blob_is_reset(&event) );
336
+ content_deltify(rid, nrid, 0);
337
+ db_end_transaction(0);
338
+ return 1;
339
+}
224340
225341
/*
226342
** WEBPAGE: technoteedit
227343
** WEBPAGE: eventedit
228344
**
@@ -323,97 +439,19 @@
323439
);
324440
}
325441
}
326442
zETime = db_text(0, "SELECT coalesce(datetime(%Q),datetime('now'))", zETime);
327443
if( P("submit")!=0 && (zBody!=0 && zComment!=0) ){
328
- char *zDate;
329
- Blob cksum;
330
- int nrid, n;
331
- blob_init(&event, 0, 0);
332
- db_begin_transaction();
333444
login_verify_csrf_secret();
334
- while( fossil_isspace(zComment[0]) ) zComment++;
335
- n = strlen(zComment);
336
- while( n>0 && fossil_isspace(zComment[n-1]) ){ n--; }
337
- if( n>0 ){
338
- blob_appendf(&event, "C %#F\n", n, zComment);
339
- }
340
- zDate = date_in_standard_format("now");
341
- blob_appendf(&event, "D %s\n", zDate);
342
- free(zDate);
343
- zETime[10] = 'T';
344
- blob_appendf(&event, "E %s %s\n", zETime, zId);
345
- zETime[10] = ' ';
346
- if( rid ){
347
- char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
348
- blob_appendf(&event, "P %s\n", zUuid);
349
- free(zUuid);
350
- }
351
- if( zMimetype && zMimetype[0] ){
352
- blob_appendf(&event, "N %s\n", zMimetype);
353
- }
354
- if( zClr && zClr[0] ){
355
- blob_appendf(&event, "T +bgcolor * %F\n", zClr);
356
- }
357
- if( zTags && zTags[0] ){
358
- Blob tags, one;
359
- int i, j;
360
- Stmt q;
361
- char *zBlob;
362
-
363
- /* Load the tags string into a blob */
364
- blob_zero(&tags);
365
- blob_append(&tags, zTags, -1);
366
-
367
- /* Collapse all sequences of whitespace and "," characters into
368
- ** a single space character */
369
- zBlob = blob_str(&tags);
370
- for(i=j=0; zBlob[i]; i++, j++){
371
- if( fossil_isspace(zBlob[i]) || zBlob[i]==',' ){
372
- while( fossil_isspace(zBlob[i+1]) ){ i++; }
373
- zBlob[j] = ' ';
374
- }else{
375
- zBlob[j] = zBlob[i];
376
- }
377
- }
378
- blob_resize(&tags, j);
379
-
380
- /* Parse out each tag and load it into a temporary table for sorting */
381
- db_multi_exec("CREATE TEMP TABLE newtags(x);");
382
- while( blob_token(&tags, &one) ){
383
- db_multi_exec("INSERT INTO newtags VALUES(%B)", &one);
384
- }
385
- blob_reset(&tags);
386
-
387
- /* Extract the tags in sorted order and make an entry in the
388
- ** artifact for each. */
389
- db_prepare(&q, "SELECT x FROM newtags ORDER BY x");
390
- while( db_step(&q)==SQLITE_ROW ){
391
- blob_appendf(&event, "T +sym-%F *\n", db_column_text(&q, 0));
392
- }
393
- db_finalize(&q);
394
- }
395
- if( !login_is_nobody() ){
396
- blob_appendf(&event, "U %F\n", login_name());
397
- }
398
- blob_appendf(&event, "W %d\n%s\n", strlen(zBody), zBody);
399
- md5sum_blob(&event, &cksum);
400
- blob_appendf(&event, "Z %b\n", &cksum);
401
- blob_reset(&cksum);
402
- nrid = content_put(&event);
403
- db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
404
- if( manifest_crosslink(nrid, &event, MC_NONE)==0 ){
405
- db_end_transaction(1);
445
+ if ( !event_commit_common(rid, zId, zBody, zETime,
446
+ zMimetype, zComment, zTags, zClr) ){
406447
style_header("Error");
407448
@ Internal error: Fossil tried to make an invalid artifact for
408
- @ the edited technode.
449
+ @ the edited technote.
409450
style_footer();
410451
return;
411452
}
412
- assert( blob_is_reset(&event) );
413
- content_deltify(rid, nrid, 0);
414
- db_end_transaction(0);
415453
cgi_redirectf("technote?name=%T", zId);
416454
}
417455
if( P("cancel")!=0 ){
418456
cgi_redirectf("technote?name=%T", zId);
419457
return;
@@ -497,5 +535,61 @@
497535
@ <input type="submit" name="cancel" value="Cancel" />
498536
@ </td></tr></table>
499537
@ </div></form>
500538
style_footer();
501539
}
540
+
541
+/*
542
+** Add a new tech note to the repository. The timestamp is
543
+** given by the zETime parameter. isNew must be true to create
544
+** a new page. If no previous page with the name zPageName exists
545
+** and isNew is false, then this routine throws an error.
546
+*/
547
+void event_cmd_commit(
548
+ char *zETime, /* timestamp */
549
+ int isNew, /* true to create a new page */
550
+ Blob *pContent, /* content of the new page */
551
+ const char *zMimeType, /* mimetype of the content */
552
+ const char *zComment, /* comment to go on the timeline */
553
+ const char *zTags, /* tags */
554
+ const char *zClr /* background color */
555
+){
556
+ int rid; /* Artifact id of the tech note */
557
+ const char *zId; /* id of the tech note */
558
+ rid = db_int(0, "SELECT objid FROM event"
559
+ " WHERE datetime(mtime)=datetime('%q') AND type = 'e'"
560
+ " LIMIT 1",
561
+ zETime
562
+ );
563
+ if( rid==0 && !isNew ){
564
+#ifdef FOSSIL_ENABLE_JSON
565
+ g.json.resultCode = FSL_JSON_E_RESOURCE_NOT_FOUND;
566
+#endif
567
+ fossil_fatal("no such tech note: %s", zETime);
568
+ }
569
+ if( rid!=0 && isNew ){
570
+#ifdef FOSSIL_ENABLE_JSON
571
+ g.json.resultCode = FSL_JSON_E_RESOURCE_ALREADY_EXISTS;
572
+#endif
573
+ fossil_fatal("tech note %s already exists", zETime);
574
+ }
575
+
576
+ if ( isNew ){
577
+ zId = db_text(0, "SELECT lower(hex(randomblob(20)))");
578
+ }else{
579
+ zId = db_text(0,
580
+ "SELECT substr(tagname,7) FROM tag"
581
+ " WHERE tagid=(SELECT tagid FROM event WHERE objid='%d')",
582
+ rid
583
+ );
584
+ }
585
+
586
+ user_select();
587
+ if (event_commit_common(rid, zId, blob_str(pContent), zETime,
588
+ zMimeType, zComment, zTags, zClr)==0 ){
589
+#ifdef FOSSIL_ENABLE_JSON
590
+ g.json.resultCode = FSL_JSON_E_ASSERT;
591
+#endif
592
+ fossil_fatal("Internal error: Fossil tried to make an "
593
+ "invalid artifact for the technote.");
594
+ }
595
+}
502596
--- src/event.c
+++ src/event.c
@@ -62,11 +62,11 @@
62 ** Display an existing event identified by EVENTID
63 */
64 void event_page(void){
65 int rid = 0; /* rid of the event artifact */
66 char *zUuid; /* UUID corresponding to rid */
67 const char *zId; /* Event identifier */
68 const char *zVerbose; /* Value of verbose option */
69 char *zETime; /* Time of the tech-note */
70 char *zATime; /* Time the artifact was created */
71 int specRid; /* rid specified by aid= parameter */
72 int prevRid, nextRid; /* Previous or next edits of this tech-note */
@@ -75,10 +75,11 @@
75 Blob title; /* Title extracted from the technote body */
76 Blob tail; /* Event body that comes after the title */
77 Stmt q1; /* Query to search for the technote */
78 int verboseFlag; /* True to show details */
79 const char *zMimetype = 0; /* Mimetype of the document */
 
80
81
82 /* wiki-read privilege is needed in order to read tech-notes.
83 */
84 login_check_credentials();
@@ -150,10 +151,15 @@
150 tail = fullbody;
151 }
152 style_header("%s", blob_str(&title));
153 if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){
154 style_submenu_element("Edit", 0, "%R/technoteedit?name=%!S", zId);
 
 
 
 
 
155 }
156 zETime = db_text(0, "SELECT datetime(%.17g)", pTNote->rEventDate);
157 style_submenu_element("Context", 0, "%R/timeline?c=%.20s", zId);
158 if( g.perm.Hyperlink ){
159 if( verboseFlag ){
@@ -216,13 +222,123 @@
216 }else{
217 @ <pre>
218 @ %h(blob_str(&fullbody))
219 @ </pre>
220 }
 
 
 
 
 
221 style_footer();
222 manifest_destroy(pTNote);
223 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
225 /*
226 ** WEBPAGE: technoteedit
227 ** WEBPAGE: eventedit
228 **
@@ -323,97 +439,19 @@
323 );
324 }
325 }
326 zETime = db_text(0, "SELECT coalesce(datetime(%Q),datetime('now'))", zETime);
327 if( P("submit")!=0 && (zBody!=0 && zComment!=0) ){
328 char *zDate;
329 Blob cksum;
330 int nrid, n;
331 blob_init(&event, 0, 0);
332 db_begin_transaction();
333 login_verify_csrf_secret();
334 while( fossil_isspace(zComment[0]) ) zComment++;
335 n = strlen(zComment);
336 while( n>0 && fossil_isspace(zComment[n-1]) ){ n--; }
337 if( n>0 ){
338 blob_appendf(&event, "C %#F\n", n, zComment);
339 }
340 zDate = date_in_standard_format("now");
341 blob_appendf(&event, "D %s\n", zDate);
342 free(zDate);
343 zETime[10] = 'T';
344 blob_appendf(&event, "E %s %s\n", zETime, zId);
345 zETime[10] = ' ';
346 if( rid ){
347 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
348 blob_appendf(&event, "P %s\n", zUuid);
349 free(zUuid);
350 }
351 if( zMimetype && zMimetype[0] ){
352 blob_appendf(&event, "N %s\n", zMimetype);
353 }
354 if( zClr && zClr[0] ){
355 blob_appendf(&event, "T +bgcolor * %F\n", zClr);
356 }
357 if( zTags && zTags[0] ){
358 Blob tags, one;
359 int i, j;
360 Stmt q;
361 char *zBlob;
362
363 /* Load the tags string into a blob */
364 blob_zero(&tags);
365 blob_append(&tags, zTags, -1);
366
367 /* Collapse all sequences of whitespace and "," characters into
368 ** a single space character */
369 zBlob = blob_str(&tags);
370 for(i=j=0; zBlob[i]; i++, j++){
371 if( fossil_isspace(zBlob[i]) || zBlob[i]==',' ){
372 while( fossil_isspace(zBlob[i+1]) ){ i++; }
373 zBlob[j] = ' ';
374 }else{
375 zBlob[j] = zBlob[i];
376 }
377 }
378 blob_resize(&tags, j);
379
380 /* Parse out each tag and load it into a temporary table for sorting */
381 db_multi_exec("CREATE TEMP TABLE newtags(x);");
382 while( blob_token(&tags, &one) ){
383 db_multi_exec("INSERT INTO newtags VALUES(%B)", &one);
384 }
385 blob_reset(&tags);
386
387 /* Extract the tags in sorted order and make an entry in the
388 ** artifact for each. */
389 db_prepare(&q, "SELECT x FROM newtags ORDER BY x");
390 while( db_step(&q)==SQLITE_ROW ){
391 blob_appendf(&event, "T +sym-%F *\n", db_column_text(&q, 0));
392 }
393 db_finalize(&q);
394 }
395 if( !login_is_nobody() ){
396 blob_appendf(&event, "U %F\n", login_name());
397 }
398 blob_appendf(&event, "W %d\n%s\n", strlen(zBody), zBody);
399 md5sum_blob(&event, &cksum);
400 blob_appendf(&event, "Z %b\n", &cksum);
401 blob_reset(&cksum);
402 nrid = content_put(&event);
403 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
404 if( manifest_crosslink(nrid, &event, MC_NONE)==0 ){
405 db_end_transaction(1);
406 style_header("Error");
407 @ Internal error: Fossil tried to make an invalid artifact for
408 @ the edited technode.
409 style_footer();
410 return;
411 }
412 assert( blob_is_reset(&event) );
413 content_deltify(rid, nrid, 0);
414 db_end_transaction(0);
415 cgi_redirectf("technote?name=%T", zId);
416 }
417 if( P("cancel")!=0 ){
418 cgi_redirectf("technote?name=%T", zId);
419 return;
@@ -497,5 +535,61 @@
497 @ <input type="submit" name="cancel" value="Cancel" />
498 @ </td></tr></table>
499 @ </div></form>
500 style_footer();
501 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
502
--- src/event.c
+++ src/event.c
@@ -62,11 +62,11 @@
62 ** Display an existing event identified by EVENTID
63 */
64 void event_page(void){
65 int rid = 0; /* rid of the event artifact */
66 char *zUuid; /* UUID corresponding to rid */
67 const char *zId; /* Event identifier */
68 const char *zVerbose; /* Value of verbose option */
69 char *zETime; /* Time of the tech-note */
70 char *zATime; /* Time the artifact was created */
71 int specRid; /* rid specified by aid= parameter */
72 int prevRid, nextRid; /* Previous or next edits of this tech-note */
@@ -75,10 +75,11 @@
75 Blob title; /* Title extracted from the technote body */
76 Blob tail; /* Event body that comes after the title */
77 Stmt q1; /* Query to search for the technote */
78 int verboseFlag; /* True to show details */
79 const char *zMimetype = 0; /* Mimetype of the document */
80 const char *zFullId; /* Full event identifier */
81
82
83 /* wiki-read privilege is needed in order to read tech-notes.
84 */
85 login_check_credentials();
@@ -150,10 +151,15 @@
151 tail = fullbody;
152 }
153 style_header("%s", blob_str(&title));
154 if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){
155 style_submenu_element("Edit", 0, "%R/technoteedit?name=%!S", zId);
156 if( g.perm.Attach ){
157 style_submenu_element("Attach", "Add an attachment",
158 "%R/attachadd?technote=%!S&from=%R/technote/%!S",
159 zId, zId);
160 }
161 }
162 zETime = db_text(0, "SELECT datetime(%.17g)", pTNote->rEventDate);
163 style_submenu_element("Context", 0, "%R/timeline?c=%.20s", zId);
164 if( g.perm.Hyperlink ){
165 if( verboseFlag ){
@@ -216,13 +222,123 @@
222 }else{
223 @ <pre>
224 @ %h(blob_str(&fullbody))
225 @ </pre>
226 }
227 zFullId = db_text(0, "SELECT SUBSTR(tagname,7)"
228 " FROM tag"
229 " WHERE tagname GLOB 'event-%q*'",
230 zId);
231 attachment_list(zFullId, "<hr /><h2>Attachments:</h2><ul>");
232 style_footer();
233 manifest_destroy(pTNote);
234 }
235
236 /*
237 ** Add or update a new tech note to the repository. rid is id of
238 ** the prior version of this technote, if any.
239 **
240 ** returns 1 if the tech note was added or updated, 0 if the
241 ** update failed making an invalid artifact
242 */
243 int event_commit_common(
244 int rid, /* id of the prior version of the technote */
245 const char *zId, /* hash label for the technote */
246 const char *zBody, /* content of the technote */
247 char *zETime, /* timestamp for the technote */
248 const char *zMimetype, /* mimetype for the technote N-card */
249 const char *zComment, /* comment shown on the timeline */
250 const char *zTags, /* tags associated with this technote */
251 const char *zClr /* Background color */
252 ){
253 Blob event;
254 char *zDate;
255 Blob cksum;
256 int nrid, n;
257
258 blob_init(&event, 0, 0);
259 db_begin_transaction();
260 while( fossil_isspace(zComment[0]) ) zComment++;
261 n = strlen(zComment);
262 while( n>0 && fossil_isspace(zComment[n-1]) ){ n--; }
263 if( n>0 ){
264 blob_appendf(&event, "C %#F\n", n, zComment);
265 }
266 zDate = date_in_standard_format("now");
267 blob_appendf(&event, "D %s\n", zDate);
268 free(zDate);
269
270 zETime[10] = 'T';
271 blob_appendf(&event, "E %s %s\n", zETime, zId);
272 zETime[10] = ' ';
273 if( rid ){
274 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
275 blob_appendf(&event, "P %s\n", zUuid);
276 free(zUuid);
277 }
278 if( zMimetype && zMimetype[0] ){
279 blob_appendf(&event, "N %s\n", zMimetype);
280 }
281 if( zClr && zClr[0] ){
282 blob_appendf(&event, "T +bgcolor * %F\n", zClr);
283 }
284 if( zTags && zTags[0] ){
285 Blob tags, one;
286 int i, j;
287 Stmt q;
288 char *zBlob;
289
290 /* Load the tags string into a blob */
291 blob_zero(&tags);
292 blob_append(&tags, zTags, -1);
293
294 /* Collapse all sequences of whitespace and "," characters into
295 ** a single space character */
296 zBlob = blob_str(&tags);
297 for(i=j=0; zBlob[i]; i++, j++){
298 if( fossil_isspace(zBlob[i]) || zBlob[i]==',' ){
299 while( fossil_isspace(zBlob[i+1]) ){ i++; }
300 zBlob[j] = ' ';
301 }else{
302 zBlob[j] = zBlob[i];
303 }
304 }
305 blob_resize(&tags, j);
306
307 /* Parse out each tag and load it into a temporary table for sorting */
308 db_multi_exec("CREATE TEMP TABLE newtags(x);");
309 while( blob_token(&tags, &one) ){
310 db_multi_exec("INSERT INTO newtags VALUES(%B)", &one);
311 }
312 blob_reset(&tags);
313
314 /* Extract the tags in sorted order and make an entry in the
315 ** artifact for each. */
316 db_prepare(&q, "SELECT x FROM newtags ORDER BY x");
317 while( db_step(&q)==SQLITE_ROW ){
318 blob_appendf(&event, "T +sym-%F *\n", db_column_text(&q, 0));
319 }
320 db_finalize(&q);
321 }
322 if( !login_is_nobody() ){
323 blob_appendf(&event, "U %F\n", login_name());
324 }
325 blob_appendf(&event, "W %d\n%s\n", strlen(zBody), zBody);
326 md5sum_blob(&event, &cksum);
327 blob_appendf(&event, "Z %b\n", &cksum);
328 blob_reset(&cksum);
329 nrid = content_put(&event);
330 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
331 if( manifest_crosslink(nrid, &event, MC_NONE)==0 ){
332 db_end_transaction(1);
333 return 0;
334 }
335 assert( blob_is_reset(&event) );
336 content_deltify(rid, nrid, 0);
337 db_end_transaction(0);
338 return 1;
339 }
340
341 /*
342 ** WEBPAGE: technoteedit
343 ** WEBPAGE: eventedit
344 **
@@ -323,97 +439,19 @@
439 );
440 }
441 }
442 zETime = db_text(0, "SELECT coalesce(datetime(%Q),datetime('now'))", zETime);
443 if( P("submit")!=0 && (zBody!=0 && zComment!=0) ){
 
 
 
 
 
444 login_verify_csrf_secret();
445 if ( !event_commit_common(rid, zId, zBody, zETime,
446 zMimetype, zComment, zTags, zClr) ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447 style_header("Error");
448 @ Internal error: Fossil tried to make an invalid artifact for
449 @ the edited technote.
450 style_footer();
451 return;
452 }
 
 
 
453 cgi_redirectf("technote?name=%T", zId);
454 }
455 if( P("cancel")!=0 ){
456 cgi_redirectf("technote?name=%T", zId);
457 return;
@@ -497,5 +535,61 @@
535 @ <input type="submit" name="cancel" value="Cancel" />
536 @ </td></tr></table>
537 @ </div></form>
538 style_footer();
539 }
540
541 /*
542 ** Add a new tech note to the repository. The timestamp is
543 ** given by the zETime parameter. isNew must be true to create
544 ** a new page. If no previous page with the name zPageName exists
545 ** and isNew is false, then this routine throws an error.
546 */
547 void event_cmd_commit(
548 char *zETime, /* timestamp */
549 int isNew, /* true to create a new page */
550 Blob *pContent, /* content of the new page */
551 const char *zMimeType, /* mimetype of the content */
552 const char *zComment, /* comment to go on the timeline */
553 const char *zTags, /* tags */
554 const char *zClr /* background color */
555 ){
556 int rid; /* Artifact id of the tech note */
557 const char *zId; /* id of the tech note */
558 rid = db_int(0, "SELECT objid FROM event"
559 " WHERE datetime(mtime)=datetime('%q') AND type = 'e'"
560 " LIMIT 1",
561 zETime
562 );
563 if( rid==0 && !isNew ){
564 #ifdef FOSSIL_ENABLE_JSON
565 g.json.resultCode = FSL_JSON_E_RESOURCE_NOT_FOUND;
566 #endif
567 fossil_fatal("no such tech note: %s", zETime);
568 }
569 if( rid!=0 && isNew ){
570 #ifdef FOSSIL_ENABLE_JSON
571 g.json.resultCode = FSL_JSON_E_RESOURCE_ALREADY_EXISTS;
572 #endif
573 fossil_fatal("tech note %s already exists", zETime);
574 }
575
576 if ( isNew ){
577 zId = db_text(0, "SELECT lower(hex(randomblob(20)))");
578 }else{
579 zId = db_text(0,
580 "SELECT substr(tagname,7) FROM tag"
581 " WHERE tagid=(SELECT tagid FROM event WHERE objid='%d')",
582 rid
583 );
584 }
585
586 user_select();
587 if (event_commit_common(rid, zId, blob_str(pContent), zETime,
588 zMimeType, zComment, zTags, zClr)==0 ){
589 #ifdef FOSSIL_ENABLE_JSON
590 g.json.resultCode = FSL_JSON_E_ASSERT;
591 #endif
592 fossil_fatal("Internal error: Fossil tried to make an "
593 "invalid artifact for the technote.");
594 }
595 }
596
+181 -2
--- src/finfo.c
+++ src/finfo.c
@@ -325,10 +325,13 @@
325325
if( fnid==0 ){
326326
@ No such file: %h(zFilename)
327327
style_footer();
328328
return;
329329
}
330
+ if( g.perm.Admin ){
331
+ style_submenu_element("MLink Table", "mtab", "%R/mlink?name=%t", zFilename);
332
+ }
330333
if( baseCheckin ){
331334
compute_direct_ancestors(baseCheckin);
332335
}
333336
url_add_parameter(&url, "name", zFilename);
334337
blob_zero(&sql);
@@ -396,11 +399,12 @@
396399
if( n>0 ){
397400
blob_appendf(&title, "First %d ancestors of file ", n);
398401
}else{
399402
blob_appendf(&title, "Ancestors of file ");
400403
}
401
- blob_appendf(&title,"<a href='%R/finfo?name=%T'>%h</a>", zFilename, zFilename);
404
+ blob_appendf(&title,"<a href='%R/finfo?name=%T'>%h</a>",
405
+ zFilename, zFilename);
402406
if( fShowId ) blob_appendf(&title, " (%d)", fnid);
403407
blob_appendf(&title, " from check-in %z%S</a>", zLink, zUuid);
404408
if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin);
405409
fossil_free(zUuid);
406410
}else{
@@ -469,11 +473,12 @@
469473
}
470474
memcpy(zTime, &zDate[11], 5);
471475
zTime[5] = 0;
472476
@ <tr><td class="timelineTime">
473477
@ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td>
474
- @ <td class="timelineGraph"><div id="m%d(gidx)" class="tl-nodemark"></div></td>
478
+ @ <td class="timelineGraph"><div id="m%d(gidx)" class="tl-nodemark"></div>
479
+ @ </td>
475480
if( zBgClr && zBgClr[0] ){
476481
@ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
477482
}else{
478483
@ <td class="timelineTableCell">
479484
}
@@ -554,5 +559,179 @@
554559
}
555560
@ </table>
556561
timeline_output_graph_javascript(pGraph, 0, 1);
557562
style_footer();
558563
}
564
+
565
+/*
566
+** WEBPAGE: mlink
567
+** URL: /mlink?name=FILENAME
568
+** URL: /mlink?ci=NAME
569
+**
570
+** Show all MLINK table entries for a particular file, or for
571
+** a particular check-in. This screen is intended for use by developers
572
+** in debugging Fossil.
573
+*/
574
+void mlink_page(void){
575
+ const char *zFName = P("name");
576
+ const char *zCI = P("ci");
577
+ Stmt q;
578
+
579
+ login_check_credentials();
580
+ if( !g.perm.Admin ){ login_needed(g.anon.Admin); return; }
581
+ style_header("MLINK Table");
582
+ if( zFName==0 && zCI==0 ){
583
+ @ <span class='generalError'>
584
+ @ Requires either a name= or ci= query parameter
585
+ @ </span>
586
+ }else if( zFName ){
587
+ int fnid = db_int(0,"SELECT fnid FROM filename WHERE name=%Q",zFName);
588
+ if( fnid<=0 ) fossil_fatal("no such file: \"%s\"", zFName);
589
+ db_prepare(&q,
590
+ "SELECT"
591
+ /* 0 */ " datetime(event.mtime,toLocal()),"
592
+ /* 1 */ " (SELECT uuid FROM blob WHERE rid=mlink.mid),"
593
+ /* 2 */ " (SELECT uuid FROM blob WHERE rid=mlink.pmid),"
594
+ /* 3 */ " isaux,"
595
+ /* 4 */ " (SELECT uuid FROM blob WHERE rid=mlink.fid),"
596
+ /* 5 */ " (SELECT uuid FROM blob WHERE rid=mlink.pid),"
597
+ /* 6 */ " mlink.pid,"
598
+ /* 7 */ " mperm,"
599
+ /* 8 */ " (SELECT name FROM filename WHERE fnid=mlink.pfnid)"
600
+ " FROM mlink, event"
601
+ " WHERE mlink.fnid=%d"
602
+ " AND event.objid=mlink.mid"
603
+ " ORDER BY 1 DESC",
604
+ fnid
605
+ );
606
+ @ <h1>MLINK table for file
607
+ @ <a href='%R/finfo?name=%t(zFName)'>%h(zFName)</a></h1>
608
+ @ <div class='brlist'>
609
+ @ <table id='mlinktable'>
610
+ @ <thead><tr>
611
+ @ <th>Date</th>
612
+ @ <th>Check-in</th>
613
+ @ <th>Parent Check-in</th>
614
+ @ <th>Merge?</th>
615
+ @ <th>New</th>
616
+ @ <th>Old</th>
617
+ @ <th>Exe Bit?</th>
618
+ @ <th>Prior Name</th>
619
+ @ </tr></thead>
620
+ @ <tbody>
621
+ while( db_step(&q)==SQLITE_ROW ){
622
+ const char *zDate = db_column_text(&q,0);
623
+ const char *zCkin = db_column_text(&q,1);
624
+ const char *zParent = db_column_text(&q,2);
625
+ int isMerge = db_column_int(&q,3);
626
+ const char *zFid = db_column_text(&q,4);
627
+ const char *zPid = db_column_text(&q,5);
628
+ int isExe = db_column_int(&q,7);
629
+ const char *zPrior = db_column_text(&q,8);
630
+ @ <tr>
631
+ @ <td><a href='%R/timeline?c=%!S(zCkin)'>%s(zDate)</a></td>
632
+ @ <td><a href='%R/info/%!S(zCkin)'>%S(zCkin)</a></td>
633
+ if( zParent ){
634
+ @ <td><a href='%R/info/%!S(zPid)'>%S(zParent)</a></td>
635
+ }else{
636
+ @ <td><i>(New)</i></td>
637
+ }
638
+ @ <td align='center'>%s(isMerge?"&#x2713;":"")</td>
639
+ if( zFid ){
640
+ @ <td><a href='%R/info/%!S(zFid)'>%S(zFid)</a></td>
641
+ }else{
642
+ @ <td><i>(Deleted)</i></td>
643
+ }
644
+ if( zPid ){
645
+ @ <td><a href='%R/info/%!S(zPid)'>%S(zPid)</a>
646
+ }else if( db_column_int(&q,6)<0 ){
647
+ @ <td><i>(Added by merge)</i></td>
648
+ }else{
649
+ @ <td><i>(New)</i></td>
650
+ }
651
+ @ <td align='center'>%s(isExe?"&#x2713;":"")</td>
652
+ if( zPrior ){
653
+ @ <td><a href='%R/finfo?name=%t(zPrior)'>%h(zPrior)</a></td>
654
+ }else{
655
+ @ <td></td>
656
+ }
657
+ @ </tr>
658
+ }
659
+ db_finalize(&q);
660
+ @ </tbody>
661
+ @ </table>
662
+ @ </div>
663
+ output_table_sorting_javascript("mlinktable","tttxtttt",1);
664
+ }else{
665
+ int mid = name_to_rid_www("ci");
666
+ db_prepare(&q,
667
+ "SELECT"
668
+ /* 0 */ " (SELECT name FROM filename WHERE fnid=mlink.fnid),"
669
+ /* 1 */ " (SELECT uuid FROM blob WHERE rid=mlink.fid),"
670
+ /* 2 */ " pid,"
671
+ /* 3 */ " (SELECT uuid FROM blob WHERE rid=mlink.pid),"
672
+ /* 4 */ " (SELECT name FROM filename WHERE fnid=mlink.pfnid),"
673
+ /* 5 */ " (SELECT uuid FROM blob WHERE rid=mlink.pmid),"
674
+ /* 6 */ " mperm,"
675
+ /* 7 */ " isaux"
676
+ " FROM mlink WHERE mid=%d ORDER BY 1",
677
+ mid
678
+ );
679
+ @ <h1>MLINK table for check-in %h(zCI)</h1>
680
+ render_checkin_context(mid, 1);
681
+ @ <hr>
682
+ @ <div class='brlist'>
683
+ @ <table id='mlinktable'>
684
+ @ <thead><tr>
685
+ @ <th>File</th>
686
+ @ <th>From</th>
687
+ @ <th>Merge?</th>
688
+ @ <th>New</th>
689
+ @ <th>Old</th>
690
+ @ <th>Exe Bit?</th>
691
+ @ <th>Prior Name</th>
692
+ @ </tr></thead>
693
+ @ <tbody>
694
+ while( db_step(&q)==SQLITE_ROW ){
695
+ const char *zName = db_column_text(&q,0);
696
+ const char *zFid = db_column_text(&q,1);
697
+ const char *zPid = db_column_text(&q,3);
698
+ const char *zPrior = db_column_text(&q,4);
699
+ const char *zParent = db_column_text(&q,5);
700
+ int isExec = db_column_int(&q,6);
701
+ int isAux = db_column_int(&q,7);
702
+ @ <tr>
703
+ @ <td><a href='%R/finfo?name=%t(zName)'>%h(zName)</a></td>
704
+ if( zParent ){
705
+ @ <td><a href='%R/info/%!S(zPid)'>%S(zParent)</a></td>
706
+ }else{
707
+ @ <td><i>(New)</i></td>
708
+ }
709
+ @ <td align='center'>%s(isAux?"&#x2713;":"")</td>
710
+ if( zFid ){
711
+ @ <td><a href='%R/info/%!S(zFid)'>%S(zFid)</a></td>
712
+ }else{
713
+ @ <td><i>(Deleted)</i></td>
714
+ }
715
+ if( zPid ){
716
+ @ <td><a href='%R/info/%!S(zPid)'>%S(zPid)</a>
717
+ }else if( db_column_int(&q,2)<0 ){
718
+ @ <td><i>(Added by merge)</i></td>
719
+ }else{
720
+ @ <td><i>(New)</i></td>
721
+ }
722
+ @ <td align='center'>%s(isExec?"&#x2713;":"")</td>
723
+ if( zPrior ){
724
+ @ <td><a href='%R/finfo?name=%t(zPrior)'>%h(zPrior)</a></td>
725
+ }else{
726
+ @ <td></td>
727
+ }
728
+ @ </tr>
729
+ }
730
+ db_finalize(&q);
731
+ @ </tbody>
732
+ @ </table>
733
+ @ </div>
734
+ output_table_sorting_javascript("mlinktable","ttxtttt",1);
735
+ }
736
+ style_footer();
737
+}
559738
--- src/finfo.c
+++ src/finfo.c
@@ -325,10 +325,13 @@
325 if( fnid==0 ){
326 @ No such file: %h(zFilename)
327 style_footer();
328 return;
329 }
 
 
 
330 if( baseCheckin ){
331 compute_direct_ancestors(baseCheckin);
332 }
333 url_add_parameter(&url, "name", zFilename);
334 blob_zero(&sql);
@@ -396,11 +399,12 @@
396 if( n>0 ){
397 blob_appendf(&title, "First %d ancestors of file ", n);
398 }else{
399 blob_appendf(&title, "Ancestors of file ");
400 }
401 blob_appendf(&title,"<a href='%R/finfo?name=%T'>%h</a>", zFilename, zFilename);
 
402 if( fShowId ) blob_appendf(&title, " (%d)", fnid);
403 blob_appendf(&title, " from check-in %z%S</a>", zLink, zUuid);
404 if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin);
405 fossil_free(zUuid);
406 }else{
@@ -469,11 +473,12 @@
469 }
470 memcpy(zTime, &zDate[11], 5);
471 zTime[5] = 0;
472 @ <tr><td class="timelineTime">
473 @ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td>
474 @ <td class="timelineGraph"><div id="m%d(gidx)" class="tl-nodemark"></div></td>
 
475 if( zBgClr && zBgClr[0] ){
476 @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
477 }else{
478 @ <td class="timelineTableCell">
479 }
@@ -554,5 +559,179 @@
554 }
555 @ </table>
556 timeline_output_graph_javascript(pGraph, 0, 1);
557 style_footer();
558 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
559
--- src/finfo.c
+++ src/finfo.c
@@ -325,10 +325,13 @@
325 if( fnid==0 ){
326 @ No such file: %h(zFilename)
327 style_footer();
328 return;
329 }
330 if( g.perm.Admin ){
331 style_submenu_element("MLink Table", "mtab", "%R/mlink?name=%t", zFilename);
332 }
333 if( baseCheckin ){
334 compute_direct_ancestors(baseCheckin);
335 }
336 url_add_parameter(&url, "name", zFilename);
337 blob_zero(&sql);
@@ -396,11 +399,12 @@
399 if( n>0 ){
400 blob_appendf(&title, "First %d ancestors of file ", n);
401 }else{
402 blob_appendf(&title, "Ancestors of file ");
403 }
404 blob_appendf(&title,"<a href='%R/finfo?name=%T'>%h</a>",
405 zFilename, zFilename);
406 if( fShowId ) blob_appendf(&title, " (%d)", fnid);
407 blob_appendf(&title, " from check-in %z%S</a>", zLink, zUuid);
408 if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin);
409 fossil_free(zUuid);
410 }else{
@@ -469,11 +473,12 @@
473 }
474 memcpy(zTime, &zDate[11], 5);
475 zTime[5] = 0;
476 @ <tr><td class="timelineTime">
477 @ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td>
478 @ <td class="timelineGraph"><div id="m%d(gidx)" class="tl-nodemark"></div>
479 @ </td>
480 if( zBgClr && zBgClr[0] ){
481 @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
482 }else{
483 @ <td class="timelineTableCell">
484 }
@@ -554,5 +559,179 @@
559 }
560 @ </table>
561 timeline_output_graph_javascript(pGraph, 0, 1);
562 style_footer();
563 }
564
565 /*
566 ** WEBPAGE: mlink
567 ** URL: /mlink?name=FILENAME
568 ** URL: /mlink?ci=NAME
569 **
570 ** Show all MLINK table entries for a particular file, or for
571 ** a particular check-in. This screen is intended for use by developers
572 ** in debugging Fossil.
573 */
574 void mlink_page(void){
575 const char *zFName = P("name");
576 const char *zCI = P("ci");
577 Stmt q;
578
579 login_check_credentials();
580 if( !g.perm.Admin ){ login_needed(g.anon.Admin); return; }
581 style_header("MLINK Table");
582 if( zFName==0 && zCI==0 ){
583 @ <span class='generalError'>
584 @ Requires either a name= or ci= query parameter
585 @ </span>
586 }else if( zFName ){
587 int fnid = db_int(0,"SELECT fnid FROM filename WHERE name=%Q",zFName);
588 if( fnid<=0 ) fossil_fatal("no such file: \"%s\"", zFName);
589 db_prepare(&q,
590 "SELECT"
591 /* 0 */ " datetime(event.mtime,toLocal()),"
592 /* 1 */ " (SELECT uuid FROM blob WHERE rid=mlink.mid),"
593 /* 2 */ " (SELECT uuid FROM blob WHERE rid=mlink.pmid),"
594 /* 3 */ " isaux,"
595 /* 4 */ " (SELECT uuid FROM blob WHERE rid=mlink.fid),"
596 /* 5 */ " (SELECT uuid FROM blob WHERE rid=mlink.pid),"
597 /* 6 */ " mlink.pid,"
598 /* 7 */ " mperm,"
599 /* 8 */ " (SELECT name FROM filename WHERE fnid=mlink.pfnid)"
600 " FROM mlink, event"
601 " WHERE mlink.fnid=%d"
602 " AND event.objid=mlink.mid"
603 " ORDER BY 1 DESC",
604 fnid
605 );
606 @ <h1>MLINK table for file
607 @ <a href='%R/finfo?name=%t(zFName)'>%h(zFName)</a></h1>
608 @ <div class='brlist'>
609 @ <table id='mlinktable'>
610 @ <thead><tr>
611 @ <th>Date</th>
612 @ <th>Check-in</th>
613 @ <th>Parent Check-in</th>
614 @ <th>Merge?</th>
615 @ <th>New</th>
616 @ <th>Old</th>
617 @ <th>Exe Bit?</th>
618 @ <th>Prior Name</th>
619 @ </tr></thead>
620 @ <tbody>
621 while( db_step(&q)==SQLITE_ROW ){
622 const char *zDate = db_column_text(&q,0);
623 const char *zCkin = db_column_text(&q,1);
624 const char *zParent = db_column_text(&q,2);
625 int isMerge = db_column_int(&q,3);
626 const char *zFid = db_column_text(&q,4);
627 const char *zPid = db_column_text(&q,5);
628 int isExe = db_column_int(&q,7);
629 const char *zPrior = db_column_text(&q,8);
630 @ <tr>
631 @ <td><a href='%R/timeline?c=%!S(zCkin)'>%s(zDate)</a></td>
632 @ <td><a href='%R/info/%!S(zCkin)'>%S(zCkin)</a></td>
633 if( zParent ){
634 @ <td><a href='%R/info/%!S(zPid)'>%S(zParent)</a></td>
635 }else{
636 @ <td><i>(New)</i></td>
637 }
638 @ <td align='center'>%s(isMerge?"&#x2713;":"")</td>
639 if( zFid ){
640 @ <td><a href='%R/info/%!S(zFid)'>%S(zFid)</a></td>
641 }else{
642 @ <td><i>(Deleted)</i></td>
643 }
644 if( zPid ){
645 @ <td><a href='%R/info/%!S(zPid)'>%S(zPid)</a>
646 }else if( db_column_int(&q,6)<0 ){
647 @ <td><i>(Added by merge)</i></td>
648 }else{
649 @ <td><i>(New)</i></td>
650 }
651 @ <td align='center'>%s(isExe?"&#x2713;":"")</td>
652 if( zPrior ){
653 @ <td><a href='%R/finfo?name=%t(zPrior)'>%h(zPrior)</a></td>
654 }else{
655 @ <td></td>
656 }
657 @ </tr>
658 }
659 db_finalize(&q);
660 @ </tbody>
661 @ </table>
662 @ </div>
663 output_table_sorting_javascript("mlinktable","tttxtttt",1);
664 }else{
665 int mid = name_to_rid_www("ci");
666 db_prepare(&q,
667 "SELECT"
668 /* 0 */ " (SELECT name FROM filename WHERE fnid=mlink.fnid),"
669 /* 1 */ " (SELECT uuid FROM blob WHERE rid=mlink.fid),"
670 /* 2 */ " pid,"
671 /* 3 */ " (SELECT uuid FROM blob WHERE rid=mlink.pid),"
672 /* 4 */ " (SELECT name FROM filename WHERE fnid=mlink.pfnid),"
673 /* 5 */ " (SELECT uuid FROM blob WHERE rid=mlink.pmid),"
674 /* 6 */ " mperm,"
675 /* 7 */ " isaux"
676 " FROM mlink WHERE mid=%d ORDER BY 1",
677 mid
678 );
679 @ <h1>MLINK table for check-in %h(zCI)</h1>
680 render_checkin_context(mid, 1);
681 @ <hr>
682 @ <div class='brlist'>
683 @ <table id='mlinktable'>
684 @ <thead><tr>
685 @ <th>File</th>
686 @ <th>From</th>
687 @ <th>Merge?</th>
688 @ <th>New</th>
689 @ <th>Old</th>
690 @ <th>Exe Bit?</th>
691 @ <th>Prior Name</th>
692 @ </tr></thead>
693 @ <tbody>
694 while( db_step(&q)==SQLITE_ROW ){
695 const char *zName = db_column_text(&q,0);
696 const char *zFid = db_column_text(&q,1);
697 const char *zPid = db_column_text(&q,3);
698 const char *zPrior = db_column_text(&q,4);
699 const char *zParent = db_column_text(&q,5);
700 int isExec = db_column_int(&q,6);
701 int isAux = db_column_int(&q,7);
702 @ <tr>
703 @ <td><a href='%R/finfo?name=%t(zName)'>%h(zName)</a></td>
704 if( zParent ){
705 @ <td><a href='%R/info/%!S(zPid)'>%S(zParent)</a></td>
706 }else{
707 @ <td><i>(New)</i></td>
708 }
709 @ <td align='center'>%s(isAux?"&#x2713;":"")</td>
710 if( zFid ){
711 @ <td><a href='%R/info/%!S(zFid)'>%S(zFid)</a></td>
712 }else{
713 @ <td><i>(Deleted)</i></td>
714 }
715 if( zPid ){
716 @ <td><a href='%R/info/%!S(zPid)'>%S(zPid)</a>
717 }else if( db_column_int(&q,2)<0 ){
718 @ <td><i>(Added by merge)</i></td>
719 }else{
720 @ <td><i>(New)</i></td>
721 }
722 @ <td align='center'>%s(isExec?"&#x2713;":"")</td>
723 if( zPrior ){
724 @ <td><a href='%R/finfo?name=%t(zPrior)'>%h(zPrior)</a></td>
725 }else{
726 @ <td></td>
727 }
728 @ </tr>
729 }
730 db_finalize(&q);
731 @ </tbody>
732 @ </table>
733 @ </div>
734 output_table_sorting_javascript("mlinktable","ttxtttt",1);
735 }
736 style_footer();
737 }
738
+35 -15
--- src/import.c
+++ src/import.c
@@ -128,11 +128,16 @@
128128
** to the newly inserted artifact.
129129
**
130130
** If saveUuid is true, then pContent is a commit record. Record its
131131
** UUID in gg.zPrevCheckin.
132132
*/
133
-static int fast_insert_content(Blob *pContent, const char *zMark, int saveUuid){
133
+static int fast_insert_content(
134
+ Blob *pContent, /* Content to insert */
135
+ const char *zMark, /* Label using this mark, if not NULL */
136
+ int saveUuid, /* Save SHA1 hash in gg.zPrevCheckin */
137
+ int doParse /* Invoke manifest_crosslink() */
138
+){
134139
Blob hash;
135140
Blob cmpr;
136141
int rid;
137142
138143
sha1sum_blob(pContent, &hash);
@@ -148,10 +153,13 @@
148153
db_bind_blob(&ins, ":content", &cmpr);
149154
db_step(&ins);
150155
db_reset(&ins);
151156
blob_reset(&cmpr);
152157
rid = db_last_insert_rowid();
158
+ if( doParse ){
159
+ manifest_crosslink(rid, pContent, MC_NONE);
160
+ }
153161
}
154162
if( zMark ){
155163
db_multi_exec(
156164
"INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
157165
"VALUES(%Q,%d,%B)",
@@ -176,11 +184,11 @@
176184
** to the BLOB table.
177185
*/
178186
static void finish_blob(void){
179187
Blob content;
180188
blob_init(&content, gg.aData, gg.nData);
181
- fast_insert_content(&content, gg.zMark, 0);
189
+ fast_insert_content(&content, gg.zMark, 0, 0);
182190
blob_reset(&content);
183191
import_reset(0);
184192
}
185193
186194
/*
@@ -194,12 +202,11 @@
194202
blob_appendf(&record, "D %s\n", gg.zDate);
195203
blob_appendf(&record, "T +%F %s\n", gg.zTag, gg.zFrom);
196204
blob_appendf(&record, "U %F\n", gg.zUser);
197205
md5sum_blob(&record, &cksum);
198206
blob_appendf(&record, "Z %b\n", &cksum);
199
- fast_insert_content(&record, 0, 0);
200
- blob_reset(&record);
207
+ fast_insert_content(&record, 0, 0, 1);
201208
blob_reset(&cksum);
202209
}
203210
import_reset(0);
204211
}
205212
@@ -238,10 +245,11 @@
238245
import_prior_files();
239246
qsort(gg.aFile, gg.nFile, sizeof(gg.aFile[0]), mfile_cmp);
240247
blob_zero(&record);
241248
blob_appendf(&record, "C %F\n", gg.zComment);
242249
blob_appendf(&record, "D %s\n", gg.zDate);
250
+ if( !g.fQuiet ) fossil_print("%.10s\r", gg.zDate);
243251
for(i=0; i<gg.nFile; i++){
244252
const char *zUuid = gg.aFile[i].zUuid;
245253
if( zUuid==0 ) continue;
246254
blob_appendf(&record, "F %F %s", gg.aFile[i].zName, zUuid);
247255
if( gg.aFile[i].isExe ){
@@ -290,12 +298,11 @@
290298
db_multi_exec("INSERT INTO xbranch(tname, brnm) VALUES(%Q,%Q)",
291299
gg.zMark, gg.zBranch);
292300
blob_appendf(&record, "U %F\n", gg.zUser);
293301
md5sum_blob(&record, &cksum);
294302
blob_appendf(&record, "Z %b\n", &cksum);
295
- fast_insert_content(&record, gg.zMark, 1);
296
- blob_reset(&record);
303
+ fast_insert_content(&record, gg.zMark, 1, 1);
297304
blob_reset(&cksum);
298305
299306
/* The "git fast-export" command might output multiple "commit" lines
300307
** that reference a tag using "refs/tags/TAGNAME". The tag should only
301308
** be applied to the last commit that is output. The problem is we do not
@@ -1503,23 +1510,27 @@
15031510
** --flat The whole dump is a single branch
15041511
**
15051512
** Common Options:
15061513
** -i|--incremental allow importing into an existing repository
15071514
** -f|--force overwrite repository if already exist
1515
+** -q|--quiet omit progress output
1516
+** --no-rebuild skip the "rebuilding metadata" step
1517
+** --no-vacuum skip the final VACUUM of the database file
15081518
**
15091519
** The --incremental option allows an existing repository to be extended
15101520
** with new content.
1511
-**
15121521
**
15131522
** See also: export
15141523
*/
15151524
void import_cmd(void){
15161525
char *zPassword;
15171526
FILE *pIn;
15181527
Stmt q;
15191528
int forceFlag = find_option("force", "f", 0)!=0;
15201529
int svnFlag = find_option("svn", 0, 0)!=0;
1530
+ int omitRebuild = find_option("no-rebuild",0,0)!=0;
1531
+ int omitVacuum = find_option("no-vacuum",0,0)!=0;
15211532
15221533
/* Options common to all input formats */
15231534
int incrFlag = find_option("incremental", "i", 0)!=0;
15241535
15251536
/* Options for --svn only */
@@ -1638,33 +1649,42 @@
16381649
"CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
16391650
"CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
16401651
"CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
16411652
);
16421653
1654
+ manifest_crosslink_begin();
16431655
git_fast_import(pIn);
16441656
db_prepare(&q, "SELECT tcontent FROM xtag");
16451657
while( db_step(&q)==SQLITE_ROW ){
16461658
Blob record;
16471659
db_ephemeral_blob(&q, 0, &record);
1648
- fast_insert_content(&record, 0, 0);
1660
+ fast_insert_content(&record, 0, 0, 1);
16491661
import_reset(0);
16501662
}
16511663
db_finalize(&q);
1664
+ manifest_crosslink_end(MC_NONE);
16521665
}
16531666
16541667
verify_cancel();
16551668
db_end_transaction(0);
1656
- db_begin_transaction();
1657
- fossil_print("Rebuilding repository meta-data...\n");
1658
- rebuild_db(0, 1, !incrFlag);
1659
- verify_cancel();
1660
- db_end_transaction(0);
1661
- fossil_print("Vacuuming..."); fflush(stdout);
1662
- db_multi_exec("VACUUM");
1669
+ fossil_print(" \r");
1670
+ if( omitRebuild ){
1671
+ omitVacuum = 1;
1672
+ }else{
1673
+ db_begin_transaction();
1674
+ fossil_print("Rebuilding repository meta-data...\n");
1675
+ rebuild_db(0, 1, !incrFlag);
1676
+ verify_cancel();
1677
+ db_end_transaction(0);
1678
+ }
1679
+ if( !omitVacuum ){
1680
+ fossil_print("Vacuuming..."); fflush(stdout);
1681
+ db_multi_exec("VACUUM");
1682
+ }
16631683
fossil_print(" ok\n");
16641684
if( !incrFlag ){
16651685
fossil_print("project-id: %s\n", db_get("project-code", 0));
16661686
fossil_print("server-id: %s\n", db_get("server-code", 0));
16671687
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
16681688
fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
16691689
}
16701690
}
16711691
--- src/import.c
+++ src/import.c
@@ -128,11 +128,16 @@
128 ** to the newly inserted artifact.
129 **
130 ** If saveUuid is true, then pContent is a commit record. Record its
131 ** UUID in gg.zPrevCheckin.
132 */
133 static int fast_insert_content(Blob *pContent, const char *zMark, int saveUuid){
 
 
 
 
 
134 Blob hash;
135 Blob cmpr;
136 int rid;
137
138 sha1sum_blob(pContent, &hash);
@@ -148,10 +153,13 @@
148 db_bind_blob(&ins, ":content", &cmpr);
149 db_step(&ins);
150 db_reset(&ins);
151 blob_reset(&cmpr);
152 rid = db_last_insert_rowid();
 
 
 
153 }
154 if( zMark ){
155 db_multi_exec(
156 "INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
157 "VALUES(%Q,%d,%B)",
@@ -176,11 +184,11 @@
176 ** to the BLOB table.
177 */
178 static void finish_blob(void){
179 Blob content;
180 blob_init(&content, gg.aData, gg.nData);
181 fast_insert_content(&content, gg.zMark, 0);
182 blob_reset(&content);
183 import_reset(0);
184 }
185
186 /*
@@ -194,12 +202,11 @@
194 blob_appendf(&record, "D %s\n", gg.zDate);
195 blob_appendf(&record, "T +%F %s\n", gg.zTag, gg.zFrom);
196 blob_appendf(&record, "U %F\n", gg.zUser);
197 md5sum_blob(&record, &cksum);
198 blob_appendf(&record, "Z %b\n", &cksum);
199 fast_insert_content(&record, 0, 0);
200 blob_reset(&record);
201 blob_reset(&cksum);
202 }
203 import_reset(0);
204 }
205
@@ -238,10 +245,11 @@
238 import_prior_files();
239 qsort(gg.aFile, gg.nFile, sizeof(gg.aFile[0]), mfile_cmp);
240 blob_zero(&record);
241 blob_appendf(&record, "C %F\n", gg.zComment);
242 blob_appendf(&record, "D %s\n", gg.zDate);
 
243 for(i=0; i<gg.nFile; i++){
244 const char *zUuid = gg.aFile[i].zUuid;
245 if( zUuid==0 ) continue;
246 blob_appendf(&record, "F %F %s", gg.aFile[i].zName, zUuid);
247 if( gg.aFile[i].isExe ){
@@ -290,12 +298,11 @@
290 db_multi_exec("INSERT INTO xbranch(tname, brnm) VALUES(%Q,%Q)",
291 gg.zMark, gg.zBranch);
292 blob_appendf(&record, "U %F\n", gg.zUser);
293 md5sum_blob(&record, &cksum);
294 blob_appendf(&record, "Z %b\n", &cksum);
295 fast_insert_content(&record, gg.zMark, 1);
296 blob_reset(&record);
297 blob_reset(&cksum);
298
299 /* The "git fast-export" command might output multiple "commit" lines
300 ** that reference a tag using "refs/tags/TAGNAME". The tag should only
301 ** be applied to the last commit that is output. The problem is we do not
@@ -1503,23 +1510,27 @@
1503 ** --flat The whole dump is a single branch
1504 **
1505 ** Common Options:
1506 ** -i|--incremental allow importing into an existing repository
1507 ** -f|--force overwrite repository if already exist
 
 
 
1508 **
1509 ** The --incremental option allows an existing repository to be extended
1510 ** with new content.
1511 **
1512 **
1513 ** See also: export
1514 */
1515 void import_cmd(void){
1516 char *zPassword;
1517 FILE *pIn;
1518 Stmt q;
1519 int forceFlag = find_option("force", "f", 0)!=0;
1520 int svnFlag = find_option("svn", 0, 0)!=0;
 
 
1521
1522 /* Options common to all input formats */
1523 int incrFlag = find_option("incremental", "i", 0)!=0;
1524
1525 /* Options for --svn only */
@@ -1638,33 +1649,42 @@
1638 "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
1639 "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
1640 "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
1641 );
1642
 
1643 git_fast_import(pIn);
1644 db_prepare(&q, "SELECT tcontent FROM xtag");
1645 while( db_step(&q)==SQLITE_ROW ){
1646 Blob record;
1647 db_ephemeral_blob(&q, 0, &record);
1648 fast_insert_content(&record, 0, 0);
1649 import_reset(0);
1650 }
1651 db_finalize(&q);
 
1652 }
1653
1654 verify_cancel();
1655 db_end_transaction(0);
1656 db_begin_transaction();
1657 fossil_print("Rebuilding repository meta-data...\n");
1658 rebuild_db(0, 1, !incrFlag);
1659 verify_cancel();
1660 db_end_transaction(0);
1661 fossil_print("Vacuuming..."); fflush(stdout);
1662 db_multi_exec("VACUUM");
 
 
 
 
 
 
 
1663 fossil_print(" ok\n");
1664 if( !incrFlag ){
1665 fossil_print("project-id: %s\n", db_get("project-code", 0));
1666 fossil_print("server-id: %s\n", db_get("server-code", 0));
1667 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
1668 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
1669 }
1670 }
1671
--- src/import.c
+++ src/import.c
@@ -128,11 +128,16 @@
128 ** to the newly inserted artifact.
129 **
130 ** If saveUuid is true, then pContent is a commit record. Record its
131 ** UUID in gg.zPrevCheckin.
132 */
133 static int fast_insert_content(
134 Blob *pContent, /* Content to insert */
135 const char *zMark, /* Label using this mark, if not NULL */
136 int saveUuid, /* Save SHA1 hash in gg.zPrevCheckin */
137 int doParse /* Invoke manifest_crosslink() */
138 ){
139 Blob hash;
140 Blob cmpr;
141 int rid;
142
143 sha1sum_blob(pContent, &hash);
@@ -148,10 +153,13 @@
153 db_bind_blob(&ins, ":content", &cmpr);
154 db_step(&ins);
155 db_reset(&ins);
156 blob_reset(&cmpr);
157 rid = db_last_insert_rowid();
158 if( doParse ){
159 manifest_crosslink(rid, pContent, MC_NONE);
160 }
161 }
162 if( zMark ){
163 db_multi_exec(
164 "INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
165 "VALUES(%Q,%d,%B)",
@@ -176,11 +184,11 @@
184 ** to the BLOB table.
185 */
186 static void finish_blob(void){
187 Blob content;
188 blob_init(&content, gg.aData, gg.nData);
189 fast_insert_content(&content, gg.zMark, 0, 0);
190 blob_reset(&content);
191 import_reset(0);
192 }
193
194 /*
@@ -194,12 +202,11 @@
202 blob_appendf(&record, "D %s\n", gg.zDate);
203 blob_appendf(&record, "T +%F %s\n", gg.zTag, gg.zFrom);
204 blob_appendf(&record, "U %F\n", gg.zUser);
205 md5sum_blob(&record, &cksum);
206 blob_appendf(&record, "Z %b\n", &cksum);
207 fast_insert_content(&record, 0, 0, 1);
 
208 blob_reset(&cksum);
209 }
210 import_reset(0);
211 }
212
@@ -238,10 +245,11 @@
245 import_prior_files();
246 qsort(gg.aFile, gg.nFile, sizeof(gg.aFile[0]), mfile_cmp);
247 blob_zero(&record);
248 blob_appendf(&record, "C %F\n", gg.zComment);
249 blob_appendf(&record, "D %s\n", gg.zDate);
250 if( !g.fQuiet ) fossil_print("%.10s\r", gg.zDate);
251 for(i=0; i<gg.nFile; i++){
252 const char *zUuid = gg.aFile[i].zUuid;
253 if( zUuid==0 ) continue;
254 blob_appendf(&record, "F %F %s", gg.aFile[i].zName, zUuid);
255 if( gg.aFile[i].isExe ){
@@ -290,12 +298,11 @@
298 db_multi_exec("INSERT INTO xbranch(tname, brnm) VALUES(%Q,%Q)",
299 gg.zMark, gg.zBranch);
300 blob_appendf(&record, "U %F\n", gg.zUser);
301 md5sum_blob(&record, &cksum);
302 blob_appendf(&record, "Z %b\n", &cksum);
303 fast_insert_content(&record, gg.zMark, 1, 1);
 
304 blob_reset(&cksum);
305
306 /* The "git fast-export" command might output multiple "commit" lines
307 ** that reference a tag using "refs/tags/TAGNAME". The tag should only
308 ** be applied to the last commit that is output. The problem is we do not
@@ -1503,23 +1510,27 @@
1510 ** --flat The whole dump is a single branch
1511 **
1512 ** Common Options:
1513 ** -i|--incremental allow importing into an existing repository
1514 ** -f|--force overwrite repository if already exist
1515 ** -q|--quiet omit progress output
1516 ** --no-rebuild skip the "rebuilding metadata" step
1517 ** --no-vacuum skip the final VACUUM of the database file
1518 **
1519 ** The --incremental option allows an existing repository to be extended
1520 ** with new content.
 
1521 **
1522 ** See also: export
1523 */
1524 void import_cmd(void){
1525 char *zPassword;
1526 FILE *pIn;
1527 Stmt q;
1528 int forceFlag = find_option("force", "f", 0)!=0;
1529 int svnFlag = find_option("svn", 0, 0)!=0;
1530 int omitRebuild = find_option("no-rebuild",0,0)!=0;
1531 int omitVacuum = find_option("no-vacuum",0,0)!=0;
1532
1533 /* Options common to all input formats */
1534 int incrFlag = find_option("incremental", "i", 0)!=0;
1535
1536 /* Options for --svn only */
@@ -1638,33 +1649,42 @@
1649 "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
1650 "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
1651 "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
1652 );
1653
1654 manifest_crosslink_begin();
1655 git_fast_import(pIn);
1656 db_prepare(&q, "SELECT tcontent FROM xtag");
1657 while( db_step(&q)==SQLITE_ROW ){
1658 Blob record;
1659 db_ephemeral_blob(&q, 0, &record);
1660 fast_insert_content(&record, 0, 0, 1);
1661 import_reset(0);
1662 }
1663 db_finalize(&q);
1664 manifest_crosslink_end(MC_NONE);
1665 }
1666
1667 verify_cancel();
1668 db_end_transaction(0);
1669 fossil_print(" \r");
1670 if( omitRebuild ){
1671 omitVacuum = 1;
1672 }else{
1673 db_begin_transaction();
1674 fossil_print("Rebuilding repository meta-data...\n");
1675 rebuild_db(0, 1, !incrFlag);
1676 verify_cancel();
1677 db_end_transaction(0);
1678 }
1679 if( !omitVacuum ){
1680 fossil_print("Vacuuming..."); fflush(stdout);
1681 db_multi_exec("VACUUM");
1682 }
1683 fossil_print(" ok\n");
1684 if( !incrFlag ){
1685 fossil_print("project-id: %s\n", db_get("project-code", 0));
1686 fossil_print("server-id: %s\n", db_get("server-code", 0));
1687 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
1688 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
1689 }
1690 }
1691
+21 -12
--- src/info.c
+++ src/info.c
@@ -213,11 +213,11 @@
213213
vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
214214
if( vid ){
215215
show_common_info(vid, "checkout:", 1, 1);
216216
}
217217
fossil_print("check-ins: %d\n",
218
- db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/"));
218
+ db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/"));
219219
}else{
220220
int rid;
221221
rid = name_to_rid(g.argv[2]);
222222
if( rid==0 ){
223223
fossil_fatal("no such object: %s\n", g.argv[2]);
@@ -295,23 +295,26 @@
295295
296296
/*
297297
** Show the context graph (immediate parents and children) for
298298
** check-in rid.
299299
*/
300
-static void showContext(int rid){
300
+void render_checkin_context(int rid, int parentsOnly){
301301
Blob sql;
302302
Stmt q;
303
- @ <div class="section">Context</div>
304303
blob_zero(&sql);
305304
blob_append(&sql, timeline_query_for_www(), -1);
306305
db_multi_exec(
307306
"CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
308307
"INSERT INTO ok VALUES(%d);"
309
- "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;"
310
- "INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;",
311
- rid, rid, rid
308
+ "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;",
309
+ rid, rid
312310
);
311
+ if( !parentsOnly ){
312
+ db_multi_exec(
313
+ "INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;", rid
314
+ );
315
+ }
313316
blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
314317
db_prepare(&q, "%s", blob_sql_text(&sql));
315318
www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH, 0, 0, rid, 0);
316319
db_finalize(&q);
317320
}
@@ -598,12 +601,14 @@
598601
}else{
599602
@ <tr><th>User:</th><td>
600603
hyperlink_to_user(zUser,zDate,"</td></tr>");
601604
}
602605
if( zEComment ){
603
- @ <tr><th>Edited&nbsp;Comment:</th><td class="infoComment">%!W(zEComment)</td></tr>
604
- @ <tr><th>Original&nbsp;Comment:</th><td class="infoComment">%!W(zComment)</td></tr>
606
+ @ <tr><th>Edited&nbsp;Comment:</th>
607
+ @ <td class="infoComment">%!W(zEComment)</td></tr>
608
+ @ <tr><th>Original&nbsp;Comment:</th>
609
+ @ <td class="infoComment">%!W(zComment)</td></tr>
605610
}else{
606611
@ <tr><th>Comment:</th><td class="infoComment">%!W(zComment)</td></tr>
607612
}
608613
if( g.perm.Admin ){
609614
db_prepare(&q2,
@@ -688,11 +693,12 @@
688693
style_header("Check-in Information");
689694
login_anonymous_available();
690695
}
691696
db_finalize(&q1);
692697
showTags(rid);
693
- showContext(rid);
698
+ @ <div class="section">Context</div>
699
+ render_checkin_context(rid, 0);
694700
@ <div class="section">Changes</div>
695701
@ <div class="sectionmenu">
696702
verboseFlag = g.zPath[0]!='c';
697703
if( db_get_boolean("show-version-diffs", 0)==0 ){
698704
verboseFlag = !verboseFlag;
@@ -726,10 +732,13 @@
726732
}
727733
if( zParent ){
728734
@ %z(xhref("class='button'","%R/vpatch?from=%!S&to=%!S",zParent,zUuid))
729735
@ Patch</a>
730736
}
737
+ if( g.perm.Admin ){
738
+ @ %z(xhref("class='button'","%R/mlink?ci=%!S",zUuid))MLink Table</a>
739
+ }
731740
@</div>
732741
if( pRe ){
733742
@ <p><b>Only differences that match regular expression "%h(zRe)"
734743
@ are shown.</b></p>
735744
}
@@ -1626,11 +1635,11 @@
16261635
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
16271636
if( rid==0 ) fossil_redirect_home();
16281637
if( g.perm.Admin ){
16291638
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
16301639
if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
1631
- style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#delshun",
1640
+ style_submenu_element("Unshun","Unshun","%s/shun?accept=%s&sub=1#delshun",
16321641
g.zTop, zUuid);
16331642
}else{
16341643
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
16351644
g.zTop, zUuid);
16361645
}
@@ -1849,11 +1858,11 @@
18491858
/*NOTREACHED*/
18501859
}
18511860
if( g.perm.Admin ){
18521861
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
18531862
if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
1854
- style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#accshun",
1863
+ style_submenu_element("Unshun","Unshun","%s/shun?accept=%s&sub=1#accshun",
18551864
g.zTop, zUuid);
18561865
}else{
18571866
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
18581867
g.zTop, zUuid);
18591868
}
@@ -1926,11 +1935,11 @@
19261935
wiki_render_by_mimetype(&content, zMime);
19271936
}else if( renderAsHtml ){
19281937
@ <iframe src="%R/raw/%T(blob_str(&downloadName))?name=%s(zUuid)"
19291938
@ width="100%%" frameborder="0" marginwidth="0" marginheight="0"
19301939
@ sandbox="allow-same-origin"
1931
- @ onload="this.height = this.contentDocument.documentElement.scrollHeight;">
1940
+ @ onload="this.height=this.contentDocument.documentElement.scrollHeight;">
19321941
@ </iframe>
19331942
}else{
19341943
style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid);
19351944
blob_to_utf8_no_bom(&content, 0);
19361945
zMime = mimetype_from_content(&content);
19371946
--- src/info.c
+++ src/info.c
@@ -213,11 +213,11 @@
213 vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
214 if( vid ){
215 show_common_info(vid, "checkout:", 1, 1);
216 }
217 fossil_print("check-ins: %d\n",
218 db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/"));
219 }else{
220 int rid;
221 rid = name_to_rid(g.argv[2]);
222 if( rid==0 ){
223 fossil_fatal("no such object: %s\n", g.argv[2]);
@@ -295,23 +295,26 @@
295
296 /*
297 ** Show the context graph (immediate parents and children) for
298 ** check-in rid.
299 */
300 static void showContext(int rid){
301 Blob sql;
302 Stmt q;
303 @ <div class="section">Context</div>
304 blob_zero(&sql);
305 blob_append(&sql, timeline_query_for_www(), -1);
306 db_multi_exec(
307 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
308 "INSERT INTO ok VALUES(%d);"
309 "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;"
310 "INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;",
311 rid, rid, rid
312 );
 
 
 
 
 
313 blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
314 db_prepare(&q, "%s", blob_sql_text(&sql));
315 www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH, 0, 0, rid, 0);
316 db_finalize(&q);
317 }
@@ -598,12 +601,14 @@
598 }else{
599 @ <tr><th>User:</th><td>
600 hyperlink_to_user(zUser,zDate,"</td></tr>");
601 }
602 if( zEComment ){
603 @ <tr><th>Edited&nbsp;Comment:</th><td class="infoComment">%!W(zEComment)</td></tr>
604 @ <tr><th>Original&nbsp;Comment:</th><td class="infoComment">%!W(zComment)</td></tr>
 
 
605 }else{
606 @ <tr><th>Comment:</th><td class="infoComment">%!W(zComment)</td></tr>
607 }
608 if( g.perm.Admin ){
609 db_prepare(&q2,
@@ -688,11 +693,12 @@
688 style_header("Check-in Information");
689 login_anonymous_available();
690 }
691 db_finalize(&q1);
692 showTags(rid);
693 showContext(rid);
 
694 @ <div class="section">Changes</div>
695 @ <div class="sectionmenu">
696 verboseFlag = g.zPath[0]!='c';
697 if( db_get_boolean("show-version-diffs", 0)==0 ){
698 verboseFlag = !verboseFlag;
@@ -726,10 +732,13 @@
726 }
727 if( zParent ){
728 @ %z(xhref("class='button'","%R/vpatch?from=%!S&to=%!S",zParent,zUuid))
729 @ Patch</a>
730 }
 
 
 
731 @</div>
732 if( pRe ){
733 @ <p><b>Only differences that match regular expression "%h(zRe)"
734 @ are shown.</b></p>
735 }
@@ -1626,11 +1635,11 @@
1626 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1627 if( rid==0 ) fossil_redirect_home();
1628 if( g.perm.Admin ){
1629 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1630 if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
1631 style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#delshun",
1632 g.zTop, zUuid);
1633 }else{
1634 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1635 g.zTop, zUuid);
1636 }
@@ -1849,11 +1858,11 @@
1849 /*NOTREACHED*/
1850 }
1851 if( g.perm.Admin ){
1852 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1853 if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
1854 style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#accshun",
1855 g.zTop, zUuid);
1856 }else{
1857 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1858 g.zTop, zUuid);
1859 }
@@ -1926,11 +1935,11 @@
1926 wiki_render_by_mimetype(&content, zMime);
1927 }else if( renderAsHtml ){
1928 @ <iframe src="%R/raw/%T(blob_str(&downloadName))?name=%s(zUuid)"
1929 @ width="100%%" frameborder="0" marginwidth="0" marginheight="0"
1930 @ sandbox="allow-same-origin"
1931 @ onload="this.height = this.contentDocument.documentElement.scrollHeight;">
1932 @ </iframe>
1933 }else{
1934 style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid);
1935 blob_to_utf8_no_bom(&content, 0);
1936 zMime = mimetype_from_content(&content);
1937
--- src/info.c
+++ src/info.c
@@ -213,11 +213,11 @@
213 vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
214 if( vid ){
215 show_common_info(vid, "checkout:", 1, 1);
216 }
217 fossil_print("check-ins: %d\n",
218 db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/"));
219 }else{
220 int rid;
221 rid = name_to_rid(g.argv[2]);
222 if( rid==0 ){
223 fossil_fatal("no such object: %s\n", g.argv[2]);
@@ -295,23 +295,26 @@
295
296 /*
297 ** Show the context graph (immediate parents and children) for
298 ** check-in rid.
299 */
300 void render_checkin_context(int rid, int parentsOnly){
301 Blob sql;
302 Stmt q;
 
303 blob_zero(&sql);
304 blob_append(&sql, timeline_query_for_www(), -1);
305 db_multi_exec(
306 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
307 "INSERT INTO ok VALUES(%d);"
308 "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;",
309 rid, rid
 
310 );
311 if( !parentsOnly ){
312 db_multi_exec(
313 "INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;", rid
314 );
315 }
316 blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
317 db_prepare(&q, "%s", blob_sql_text(&sql));
318 www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH, 0, 0, rid, 0);
319 db_finalize(&q);
320 }
@@ -598,12 +601,14 @@
601 }else{
602 @ <tr><th>User:</th><td>
603 hyperlink_to_user(zUser,zDate,"</td></tr>");
604 }
605 if( zEComment ){
606 @ <tr><th>Edited&nbsp;Comment:</th>
607 @ <td class="infoComment">%!W(zEComment)</td></tr>
608 @ <tr><th>Original&nbsp;Comment:</th>
609 @ <td class="infoComment">%!W(zComment)</td></tr>
610 }else{
611 @ <tr><th>Comment:</th><td class="infoComment">%!W(zComment)</td></tr>
612 }
613 if( g.perm.Admin ){
614 db_prepare(&q2,
@@ -688,11 +693,12 @@
693 style_header("Check-in Information");
694 login_anonymous_available();
695 }
696 db_finalize(&q1);
697 showTags(rid);
698 @ <div class="section">Context</div>
699 render_checkin_context(rid, 0);
700 @ <div class="section">Changes</div>
701 @ <div class="sectionmenu">
702 verboseFlag = g.zPath[0]!='c';
703 if( db_get_boolean("show-version-diffs", 0)==0 ){
704 verboseFlag = !verboseFlag;
@@ -726,10 +732,13 @@
732 }
733 if( zParent ){
734 @ %z(xhref("class='button'","%R/vpatch?from=%!S&to=%!S",zParent,zUuid))
735 @ Patch</a>
736 }
737 if( g.perm.Admin ){
738 @ %z(xhref("class='button'","%R/mlink?ci=%!S",zUuid))MLink Table</a>
739 }
740 @</div>
741 if( pRe ){
742 @ <p><b>Only differences that match regular expression "%h(zRe)"
743 @ are shown.</b></p>
744 }
@@ -1626,11 +1635,11 @@
1635 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1636 if( rid==0 ) fossil_redirect_home();
1637 if( g.perm.Admin ){
1638 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1639 if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
1640 style_submenu_element("Unshun","Unshun","%s/shun?accept=%s&sub=1#delshun",
1641 g.zTop, zUuid);
1642 }else{
1643 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1644 g.zTop, zUuid);
1645 }
@@ -1849,11 +1858,11 @@
1858 /*NOTREACHED*/
1859 }
1860 if( g.perm.Admin ){
1861 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1862 if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
1863 style_submenu_element("Unshun","Unshun","%s/shun?accept=%s&sub=1#accshun",
1864 g.zTop, zUuid);
1865 }else{
1866 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1867 g.zTop, zUuid);
1868 }
@@ -1926,11 +1935,11 @@
1935 wiki_render_by_mimetype(&content, zMime);
1936 }else if( renderAsHtml ){
1937 @ <iframe src="%R/raw/%T(blob_str(&downloadName))?name=%s(zUuid)"
1938 @ width="100%%" frameborder="0" marginwidth="0" marginheight="0"
1939 @ sandbox="allow-same-origin"
1940 @ onload="this.height=this.contentDocument.documentElement.scrollHeight;">
1941 @ </iframe>
1942 }else{
1943 style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid);
1944 blob_to_utf8_no_bom(&content, 0);
1945 zMime = mimetype_from_content(&content);
1946
+17 -23
--- src/lookslike.c
+++ src/lookslike.c
@@ -37,21 +37,21 @@
3737
** Output flags for the looks_like_utf8() and looks_like_utf16() routines used
3838
** to convey status information about the blob content.
3939
*/
4040
#define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */
4141
#define LOOK_NUL ((int)0x00000001) /* One or more NUL chars were found. */
42
-#define LOOK_CR ((int)0x00000002) /* One or more CR chars were found. */
43
-#define LOOK_LONE_CR ((int)0x00000004) /* An unpaired CR char was found. */
44
-#define LOOK_LF ((int)0x00000008) /* One or more LF chars were found. */
45
-#define LOOK_LONE_LF ((int)0x00000010) /* An unpaired LF char was found. */
46
-#define LOOK_CRLF ((int)0x00000020) /* One or more CR/LF pairs were found. */
47
-#define LOOK_LONG ((int)0x00000040) /* An over length line was found. */
48
-#define LOOK_ODD ((int)0x00000080) /* An odd number of bytes was found. */
49
-#define LOOK_SHORT ((int)0x00000100) /* Unable to perform full check. */
50
-#define LOOK_INVALID ((int)0x00000200) /* Invalid sequence was found. */
42
+#define LOOK_LONE_CR ((int)0x00000002) /* An unpaired CR char was found. */
43
+#define LOOK_LONE_LF ((int)0x00000004) /* An unpaired LF char was found. */
44
+#define LOOK_CRLF ((int)0x00000008) /* One or more CR/LF pairs were found. */
45
+#define LOOK_LONG ((int)0x00000010) /* An over length line was found. */
46
+#define LOOK_ODD ((int)0x00000020) /* An odd number of bytes was found. */
47
+#define LOOK_SHORT ((int)0x00000040) /* Unable to perform full check. */
48
+#define LOOK_INVALID ((int)0x00000080) /* Invalid sequence was found. */
5149
#define LOOK_BINARY (LOOK_NUL | LOOK_LONG | LOOK_SHORT) /* May be binary. */
5250
#define LOOK_EOL (LOOK_LONE_CR | LOOK_LONE_LF | LOOK_CRLF) /* Line seps. */
51
+#define LOOK_CR (LOOK_LONE_CR | LOOK_CRLF) /* One or more CR chars. */
52
+#define LOOK_LF (LOOK_LONE_LF | LOOK_CRLF) /* One or more LF chars. */
5353
#endif /* INTERFACE */
5454
5555
5656
/*
5757
** This function attempts to scan each logical line within the blob to
@@ -93,37 +93,34 @@
9393
if( n==0 ) return flags; /* Empty file -> text */
9494
c = *z;
9595
if( c==0 ){
9696
flags |= LOOK_NUL; /* NUL character in a file -> binary */
9797
}else if( c=='\r' ){
98
- flags |= LOOK_CR;
9998
if( n<=1 || z[1]!='\n' ){
100
- flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
99
+ flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
101100
}
102101
}
103102
j = (c!='\n');
104
- if( !j ) flags |= (LOOK_LF | LOOK_LONE_LF); /* Found LF as first char */
103
+ if( !j ) flags |= (LOOK_LONE_LF); /* Found LF as first char */
105104
while( !(flags&stopFlags) && --n>0 ){
106105
int c2 = c;
107106
c = *++z; ++j;
108107
if( c==0 ){
109108
flags |= LOOK_NUL; /* NUL character in a file -> binary */
110109
}else if( c=='\n' ){
111
- flags |= LOOK_LF;
112110
if( c2=='\r' ){
113
- flags |= (LOOK_CR | LOOK_CRLF); /* Found LF preceded by CR */
111
+ flags |= (LOOK_CRLF); /* Found LF preceded by CR */
114112
}else{
115113
flags |= LOOK_LONE_LF;
116114
}
117115
if( j>LENGTH_MASK ){
118116
flags |= LOOK_LONG; /* Very long line -> binary */
119117
}
120118
j = 0;
121119
}else if( c=='\r' ){
122
- flags |= LOOK_CR;
123120
if( n<=1 || z[1]!='\n' ){
124
- flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
121
+ flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
125122
}
126123
}
127124
}
128125
if( n ){
129126
flags |= LOOK_SHORT; /* The whole blob was not examined */
@@ -242,17 +239,16 @@
242239
c = UTF16_SWAP(c);
243240
}
244241
if( c==0 ){
245242
flags |= LOOK_NUL; /* NUL character in a file -> binary */
246243
}else if( c=='\r' ){
247
- flags |= LOOK_CR;
248244
if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){
249
- flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
245
+ flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
250246
}
251247
}
252248
j = (c!='\n');
253
- if( !j ) flags |= (LOOK_LF | LOOK_LONE_LF); /* Found LF as first char */
249
+ if( !j ) flags |= (LOOK_LONE_LF); /* Found LF as first char */
254250
while( !(flags&stopFlags) && ((n-=sizeof(WCHAR_T))>=sizeof(WCHAR_T)) ){
255251
int c2 = c;
256252
c = *++z;
257253
if( bReverse ){
258254
c = UTF16_SWAP(c);
@@ -259,24 +255,22 @@
259255
}
260256
++j;
261257
if( c==0 ){
262258
flags |= LOOK_NUL; /* NUL character in a file -> binary */
263259
}else if( c=='\n' ){
264
- flags |= LOOK_LF;
265260
if( c2=='\r' ){
266
- flags |= (LOOK_CR | LOOK_CRLF); /* Found LF preceded by CR */
261
+ flags |= (LOOK_CRLF); /* Found LF preceded by CR */
267262
}else{
268263
flags |= LOOK_LONE_LF;
269264
}
270265
if( j>UTF16_LENGTH_MASK ){
271266
flags |= LOOK_LONG; /* Very long line -> binary */
272267
}
273268
j = 0;
274269
}else if( c=='\r' ){
275
- flags |= LOOK_CR;
276270
if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){
277
- flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
271
+ flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
278272
}
279273
}
280274
}
281275
if( n ){
282276
flags |= LOOK_SHORT; /* The whole blob was not examined */
283277
--- src/lookslike.c
+++ src/lookslike.c
@@ -37,21 +37,21 @@
37 ** Output flags for the looks_like_utf8() and looks_like_utf16() routines used
38 ** to convey status information about the blob content.
39 */
40 #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */
41 #define LOOK_NUL ((int)0x00000001) /* One or more NUL chars were found. */
42 #define LOOK_CR ((int)0x00000002) /* One or more CR chars were found. */
43 #define LOOK_LONE_CR ((int)0x00000004) /* An unpaired CR char was found. */
44 #define LOOK_LF ((int)0x00000008) /* One or more LF chars were found. */
45 #define LOOK_LONE_LF ((int)0x00000010) /* An unpaired LF char was found. */
46 #define LOOK_CRLF ((int)0x00000020) /* One or more CR/LF pairs were found. */
47 #define LOOK_LONG ((int)0x00000040) /* An over length line was found. */
48 #define LOOK_ODD ((int)0x00000080) /* An odd number of bytes was found. */
49 #define LOOK_SHORT ((int)0x00000100) /* Unable to perform full check. */
50 #define LOOK_INVALID ((int)0x00000200) /* Invalid sequence was found. */
51 #define LOOK_BINARY (LOOK_NUL | LOOK_LONG | LOOK_SHORT) /* May be binary. */
52 #define LOOK_EOL (LOOK_LONE_CR | LOOK_LONE_LF | LOOK_CRLF) /* Line seps. */
 
 
53 #endif /* INTERFACE */
54
55
56 /*
57 ** This function attempts to scan each logical line within the blob to
@@ -93,37 +93,34 @@
93 if( n==0 ) return flags; /* Empty file -> text */
94 c = *z;
95 if( c==0 ){
96 flags |= LOOK_NUL; /* NUL character in a file -> binary */
97 }else if( c=='\r' ){
98 flags |= LOOK_CR;
99 if( n<=1 || z[1]!='\n' ){
100 flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
101 }
102 }
103 j = (c!='\n');
104 if( !j ) flags |= (LOOK_LF | LOOK_LONE_LF); /* Found LF as first char */
105 while( !(flags&stopFlags) && --n>0 ){
106 int c2 = c;
107 c = *++z; ++j;
108 if( c==0 ){
109 flags |= LOOK_NUL; /* NUL character in a file -> binary */
110 }else if( c=='\n' ){
111 flags |= LOOK_LF;
112 if( c2=='\r' ){
113 flags |= (LOOK_CR | LOOK_CRLF); /* Found LF preceded by CR */
114 }else{
115 flags |= LOOK_LONE_LF;
116 }
117 if( j>LENGTH_MASK ){
118 flags |= LOOK_LONG; /* Very long line -> binary */
119 }
120 j = 0;
121 }else if( c=='\r' ){
122 flags |= LOOK_CR;
123 if( n<=1 || z[1]!='\n' ){
124 flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
125 }
126 }
127 }
128 if( n ){
129 flags |= LOOK_SHORT; /* The whole blob was not examined */
@@ -242,17 +239,16 @@
242 c = UTF16_SWAP(c);
243 }
244 if( c==0 ){
245 flags |= LOOK_NUL; /* NUL character in a file -> binary */
246 }else if( c=='\r' ){
247 flags |= LOOK_CR;
248 if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){
249 flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
250 }
251 }
252 j = (c!='\n');
253 if( !j ) flags |= (LOOK_LF | LOOK_LONE_LF); /* Found LF as first char */
254 while( !(flags&stopFlags) && ((n-=sizeof(WCHAR_T))>=sizeof(WCHAR_T)) ){
255 int c2 = c;
256 c = *++z;
257 if( bReverse ){
258 c = UTF16_SWAP(c);
@@ -259,24 +255,22 @@
259 }
260 ++j;
261 if( c==0 ){
262 flags |= LOOK_NUL; /* NUL character in a file -> binary */
263 }else if( c=='\n' ){
264 flags |= LOOK_LF;
265 if( c2=='\r' ){
266 flags |= (LOOK_CR | LOOK_CRLF); /* Found LF preceded by CR */
267 }else{
268 flags |= LOOK_LONE_LF;
269 }
270 if( j>UTF16_LENGTH_MASK ){
271 flags |= LOOK_LONG; /* Very long line -> binary */
272 }
273 j = 0;
274 }else if( c=='\r' ){
275 flags |= LOOK_CR;
276 if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){
277 flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
278 }
279 }
280 }
281 if( n ){
282 flags |= LOOK_SHORT; /* The whole blob was not examined */
283
--- src/lookslike.c
+++ src/lookslike.c
@@ -37,21 +37,21 @@
37 ** Output flags for the looks_like_utf8() and looks_like_utf16() routines used
38 ** to convey status information about the blob content.
39 */
40 #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */
41 #define LOOK_NUL ((int)0x00000001) /* One or more NUL chars were found. */
42 #define LOOK_LONE_CR ((int)0x00000002) /* An unpaired CR char was found. */
43 #define LOOK_LONE_LF ((int)0x00000004) /* An unpaired LF char was found. */
44 #define LOOK_CRLF ((int)0x00000008) /* One or more CR/LF pairs were found. */
45 #define LOOK_LONG ((int)0x00000010) /* An over length line was found. */
46 #define LOOK_ODD ((int)0x00000020) /* An odd number of bytes was found. */
47 #define LOOK_SHORT ((int)0x00000040) /* Unable to perform full check. */
48 #define LOOK_INVALID ((int)0x00000080) /* Invalid sequence was found. */
 
 
49 #define LOOK_BINARY (LOOK_NUL | LOOK_LONG | LOOK_SHORT) /* May be binary. */
50 #define LOOK_EOL (LOOK_LONE_CR | LOOK_LONE_LF | LOOK_CRLF) /* Line seps. */
51 #define LOOK_CR (LOOK_LONE_CR | LOOK_CRLF) /* One or more CR chars. */
52 #define LOOK_LF (LOOK_LONE_LF | LOOK_CRLF) /* One or more LF chars. */
53 #endif /* INTERFACE */
54
55
56 /*
57 ** This function attempts to scan each logical line within the blob to
@@ -93,37 +93,34 @@
93 if( n==0 ) return flags; /* Empty file -> text */
94 c = *z;
95 if( c==0 ){
96 flags |= LOOK_NUL; /* NUL character in a file -> binary */
97 }else if( c=='\r' ){
 
98 if( n<=1 || z[1]!='\n' ){
99 flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
100 }
101 }
102 j = (c!='\n');
103 if( !j ) flags |= (LOOK_LONE_LF); /* Found LF as first char */
104 while( !(flags&stopFlags) && --n>0 ){
105 int c2 = c;
106 c = *++z; ++j;
107 if( c==0 ){
108 flags |= LOOK_NUL; /* NUL character in a file -> binary */
109 }else if( c=='\n' ){
 
110 if( c2=='\r' ){
111 flags |= (LOOK_CRLF); /* Found LF preceded by CR */
112 }else{
113 flags |= LOOK_LONE_LF;
114 }
115 if( j>LENGTH_MASK ){
116 flags |= LOOK_LONG; /* Very long line -> binary */
117 }
118 j = 0;
119 }else if( c=='\r' ){
 
120 if( n<=1 || z[1]!='\n' ){
121 flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
122 }
123 }
124 }
125 if( n ){
126 flags |= LOOK_SHORT; /* The whole blob was not examined */
@@ -242,17 +239,16 @@
239 c = UTF16_SWAP(c);
240 }
241 if( c==0 ){
242 flags |= LOOK_NUL; /* NUL character in a file -> binary */
243 }else if( c=='\r' ){
 
244 if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){
245 flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
246 }
247 }
248 j = (c!='\n');
249 if( !j ) flags |= (LOOK_LONE_LF); /* Found LF as first char */
250 while( !(flags&stopFlags) && ((n-=sizeof(WCHAR_T))>=sizeof(WCHAR_T)) ){
251 int c2 = c;
252 c = *++z;
253 if( bReverse ){
254 c = UTF16_SWAP(c);
@@ -259,24 +255,22 @@
255 }
256 ++j;
257 if( c==0 ){
258 flags |= LOOK_NUL; /* NUL character in a file -> binary */
259 }else if( c=='\n' ){
 
260 if( c2=='\r' ){
261 flags |= (LOOK_CRLF); /* Found LF preceded by CR */
262 }else{
263 flags |= LOOK_LONE_LF;
264 }
265 if( j>UTF16_LENGTH_MASK ){
266 flags |= LOOK_LONG; /* Very long line -> binary */
267 }
268 j = 0;
269 }else if( c=='\r' ){
 
270 if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){
271 flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
272 }
273 }
274 }
275 if( n ){
276 flags |= LOOK_SHORT; /* The whole blob was not examined */
277
+17 -23
--- src/lookslike.c
+++ src/lookslike.c
@@ -37,21 +37,21 @@
3737
** Output flags for the looks_like_utf8() and looks_like_utf16() routines used
3838
** to convey status information about the blob content.
3939
*/
4040
#define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */
4141
#define LOOK_NUL ((int)0x00000001) /* One or more NUL chars were found. */
42
-#define LOOK_CR ((int)0x00000002) /* One or more CR chars were found. */
43
-#define LOOK_LONE_CR ((int)0x00000004) /* An unpaired CR char was found. */
44
-#define LOOK_LF ((int)0x00000008) /* One or more LF chars were found. */
45
-#define LOOK_LONE_LF ((int)0x00000010) /* An unpaired LF char was found. */
46
-#define LOOK_CRLF ((int)0x00000020) /* One or more CR/LF pairs were found. */
47
-#define LOOK_LONG ((int)0x00000040) /* An over length line was found. */
48
-#define LOOK_ODD ((int)0x00000080) /* An odd number of bytes was found. */
49
-#define LOOK_SHORT ((int)0x00000100) /* Unable to perform full check. */
50
-#define LOOK_INVALID ((int)0x00000200) /* Invalid sequence was found. */
42
+#define LOOK_LONE_CR ((int)0x00000002) /* An unpaired CR char was found. */
43
+#define LOOK_LONE_LF ((int)0x00000004) /* An unpaired LF char was found. */
44
+#define LOOK_CRLF ((int)0x00000008) /* One or more CR/LF pairs were found. */
45
+#define LOOK_LONG ((int)0x00000010) /* An over length line was found. */
46
+#define LOOK_ODD ((int)0x00000020) /* An odd number of bytes was found. */
47
+#define LOOK_SHORT ((int)0x00000040) /* Unable to perform full check. */
48
+#define LOOK_INVALID ((int)0x00000080) /* Invalid sequence was found. */
5149
#define LOOK_BINARY (LOOK_NUL | LOOK_LONG | LOOK_SHORT) /* May be binary. */
5250
#define LOOK_EOL (LOOK_LONE_CR | LOOK_LONE_LF | LOOK_CRLF) /* Line seps. */
51
+#define LOOK_CR (LOOK_LONE_CR | LOOK_CRLF) /* One or more CR chars. */
52
+#define LOOK_LF (LOOK_LONE_LF | LOOK_CRLF) /* One or more LF chars. */
5353
#endif /* INTERFACE */
5454
5555
5656
/*
5757
** This function attempts to scan each logical line within the blob to
@@ -93,37 +93,34 @@
9393
if( n==0 ) return flags; /* Empty file -> text */
9494
c = *z;
9595
if( c==0 ){
9696
flags |= LOOK_NUL; /* NUL character in a file -> binary */
9797
}else if( c=='\r' ){
98
- flags |= LOOK_CR;
9998
if( n<=1 || z[1]!='\n' ){
100
- flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
99
+ flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
101100
}
102101
}
103102
j = (c!='\n');
104
- if( !j ) flags |= (LOOK_LF | LOOK_LONE_LF); /* Found LF as first char */
103
+ if( !j ) flags |= (LOOK_LONE_LF); /* Found LF as first char */
105104
while( !(flags&stopFlags) && --n>0 ){
106105
int c2 = c;
107106
c = *++z; ++j;
108107
if( c==0 ){
109108
flags |= LOOK_NUL; /* NUL character in a file -> binary */
110109
}else if( c=='\n' ){
111
- flags |= LOOK_LF;
112110
if( c2=='\r' ){
113
- flags |= (LOOK_CR | LOOK_CRLF); /* Found LF preceded by CR */
111
+ flags |= (LOOK_CRLF); /* Found LF preceded by CR */
114112
}else{
115113
flags |= LOOK_LONE_LF;
116114
}
117115
if( j>LENGTH_MASK ){
118116
flags |= LOOK_LONG; /* Very long line -> binary */
119117
}
120118
j = 0;
121119
}else if( c=='\r' ){
122
- flags |= LOOK_CR;
123120
if( n<=1 || z[1]!='\n' ){
124
- flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
121
+ flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
125122
}
126123
}
127124
}
128125
if( n ){
129126
flags |= LOOK_SHORT; /* The whole blob was not examined */
@@ -242,17 +239,16 @@
242239
c = UTF16_SWAP(c);
243240
}
244241
if( c==0 ){
245242
flags |= LOOK_NUL; /* NUL character in a file -> binary */
246243
}else if( c=='\r' ){
247
- flags |= LOOK_CR;
248244
if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){
249
- flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
245
+ flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
250246
}
251247
}
252248
j = (c!='\n');
253
- if( !j ) flags |= (LOOK_LF | LOOK_LONE_LF); /* Found LF as first char */
249
+ if( !j ) flags |= (LOOK_LONE_LF); /* Found LF as first char */
254250
while( !(flags&stopFlags) && ((n-=sizeof(WCHAR_T))>=sizeof(WCHAR_T)) ){
255251
int c2 = c;
256252
c = *++z;
257253
if( bReverse ){
258254
c = UTF16_SWAP(c);
@@ -259,24 +255,22 @@
259255
}
260256
++j;
261257
if( c==0 ){
262258
flags |= LOOK_NUL; /* NUL character in a file -> binary */
263259
}else if( c=='\n' ){
264
- flags |= LOOK_LF;
265260
if( c2=='\r' ){
266
- flags |= (LOOK_CR | LOOK_CRLF); /* Found LF preceded by CR */
261
+ flags |= (LOOK_CRLF); /* Found LF preceded by CR */
267262
}else{
268263
flags |= LOOK_LONE_LF;
269264
}
270265
if( j>UTF16_LENGTH_MASK ){
271266
flags |= LOOK_LONG; /* Very long line -> binary */
272267
}
273268
j = 0;
274269
}else if( c=='\r' ){
275
- flags |= LOOK_CR;
276270
if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){
277
- flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
271
+ flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
278272
}
279273
}
280274
}
281275
if( n ){
282276
flags |= LOOK_SHORT; /* The whole blob was not examined */
283277
--- src/lookslike.c
+++ src/lookslike.c
@@ -37,21 +37,21 @@
37 ** Output flags for the looks_like_utf8() and looks_like_utf16() routines used
38 ** to convey status information about the blob content.
39 */
40 #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */
41 #define LOOK_NUL ((int)0x00000001) /* One or more NUL chars were found. */
42 #define LOOK_CR ((int)0x00000002) /* One or more CR chars were found. */
43 #define LOOK_LONE_CR ((int)0x00000004) /* An unpaired CR char was found. */
44 #define LOOK_LF ((int)0x00000008) /* One or more LF chars were found. */
45 #define LOOK_LONE_LF ((int)0x00000010) /* An unpaired LF char was found. */
46 #define LOOK_CRLF ((int)0x00000020) /* One or more CR/LF pairs were found. */
47 #define LOOK_LONG ((int)0x00000040) /* An over length line was found. */
48 #define LOOK_ODD ((int)0x00000080) /* An odd number of bytes was found. */
49 #define LOOK_SHORT ((int)0x00000100) /* Unable to perform full check. */
50 #define LOOK_INVALID ((int)0x00000200) /* Invalid sequence was found. */
51 #define LOOK_BINARY (LOOK_NUL | LOOK_LONG | LOOK_SHORT) /* May be binary. */
52 #define LOOK_EOL (LOOK_LONE_CR | LOOK_LONE_LF | LOOK_CRLF) /* Line seps. */
 
 
53 #endif /* INTERFACE */
54
55
56 /*
57 ** This function attempts to scan each logical line within the blob to
@@ -93,37 +93,34 @@
93 if( n==0 ) return flags; /* Empty file -> text */
94 c = *z;
95 if( c==0 ){
96 flags |= LOOK_NUL; /* NUL character in a file -> binary */
97 }else if( c=='\r' ){
98 flags |= LOOK_CR;
99 if( n<=1 || z[1]!='\n' ){
100 flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
101 }
102 }
103 j = (c!='\n');
104 if( !j ) flags |= (LOOK_LF | LOOK_LONE_LF); /* Found LF as first char */
105 while( !(flags&stopFlags) && --n>0 ){
106 int c2 = c;
107 c = *++z; ++j;
108 if( c==0 ){
109 flags |= LOOK_NUL; /* NUL character in a file -> binary */
110 }else if( c=='\n' ){
111 flags |= LOOK_LF;
112 if( c2=='\r' ){
113 flags |= (LOOK_CR | LOOK_CRLF); /* Found LF preceded by CR */
114 }else{
115 flags |= LOOK_LONE_LF;
116 }
117 if( j>LENGTH_MASK ){
118 flags |= LOOK_LONG; /* Very long line -> binary */
119 }
120 j = 0;
121 }else if( c=='\r' ){
122 flags |= LOOK_CR;
123 if( n<=1 || z[1]!='\n' ){
124 flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
125 }
126 }
127 }
128 if( n ){
129 flags |= LOOK_SHORT; /* The whole blob was not examined */
@@ -242,17 +239,16 @@
242 c = UTF16_SWAP(c);
243 }
244 if( c==0 ){
245 flags |= LOOK_NUL; /* NUL character in a file -> binary */
246 }else if( c=='\r' ){
247 flags |= LOOK_CR;
248 if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){
249 flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
250 }
251 }
252 j = (c!='\n');
253 if( !j ) flags |= (LOOK_LF | LOOK_LONE_LF); /* Found LF as first char */
254 while( !(flags&stopFlags) && ((n-=sizeof(WCHAR_T))>=sizeof(WCHAR_T)) ){
255 int c2 = c;
256 c = *++z;
257 if( bReverse ){
258 c = UTF16_SWAP(c);
@@ -259,24 +255,22 @@
259 }
260 ++j;
261 if( c==0 ){
262 flags |= LOOK_NUL; /* NUL character in a file -> binary */
263 }else if( c=='\n' ){
264 flags |= LOOK_LF;
265 if( c2=='\r' ){
266 flags |= (LOOK_CR | LOOK_CRLF); /* Found LF preceded by CR */
267 }else{
268 flags |= LOOK_LONE_LF;
269 }
270 if( j>UTF16_LENGTH_MASK ){
271 flags |= LOOK_LONG; /* Very long line -> binary */
272 }
273 j = 0;
274 }else if( c=='\r' ){
275 flags |= LOOK_CR;
276 if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){
277 flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
278 }
279 }
280 }
281 if( n ){
282 flags |= LOOK_SHORT; /* The whole blob was not examined */
283
--- src/lookslike.c
+++ src/lookslike.c
@@ -37,21 +37,21 @@
37 ** Output flags for the looks_like_utf8() and looks_like_utf16() routines used
38 ** to convey status information about the blob content.
39 */
40 #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */
41 #define LOOK_NUL ((int)0x00000001) /* One or more NUL chars were found. */
42 #define LOOK_LONE_CR ((int)0x00000002) /* An unpaired CR char was found. */
43 #define LOOK_LONE_LF ((int)0x00000004) /* An unpaired LF char was found. */
44 #define LOOK_CRLF ((int)0x00000008) /* One or more CR/LF pairs were found. */
45 #define LOOK_LONG ((int)0x00000010) /* An over length line was found. */
46 #define LOOK_ODD ((int)0x00000020) /* An odd number of bytes was found. */
47 #define LOOK_SHORT ((int)0x00000040) /* Unable to perform full check. */
48 #define LOOK_INVALID ((int)0x00000080) /* Invalid sequence was found. */
 
 
49 #define LOOK_BINARY (LOOK_NUL | LOOK_LONG | LOOK_SHORT) /* May be binary. */
50 #define LOOK_EOL (LOOK_LONE_CR | LOOK_LONE_LF | LOOK_CRLF) /* Line seps. */
51 #define LOOK_CR (LOOK_LONE_CR | LOOK_CRLF) /* One or more CR chars. */
52 #define LOOK_LF (LOOK_LONE_LF | LOOK_CRLF) /* One or more LF chars. */
53 #endif /* INTERFACE */
54
55
56 /*
57 ** This function attempts to scan each logical line within the blob to
@@ -93,37 +93,34 @@
93 if( n==0 ) return flags; /* Empty file -> text */
94 c = *z;
95 if( c==0 ){
96 flags |= LOOK_NUL; /* NUL character in a file -> binary */
97 }else if( c=='\r' ){
 
98 if( n<=1 || z[1]!='\n' ){
99 flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
100 }
101 }
102 j = (c!='\n');
103 if( !j ) flags |= (LOOK_LONE_LF); /* Found LF as first char */
104 while( !(flags&stopFlags) && --n>0 ){
105 int c2 = c;
106 c = *++z; ++j;
107 if( c==0 ){
108 flags |= LOOK_NUL; /* NUL character in a file -> binary */
109 }else if( c=='\n' ){
 
110 if( c2=='\r' ){
111 flags |= (LOOK_CRLF); /* Found LF preceded by CR */
112 }else{
113 flags |= LOOK_LONE_LF;
114 }
115 if( j>LENGTH_MASK ){
116 flags |= LOOK_LONG; /* Very long line -> binary */
117 }
118 j = 0;
119 }else if( c=='\r' ){
 
120 if( n<=1 || z[1]!='\n' ){
121 flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
122 }
123 }
124 }
125 if( n ){
126 flags |= LOOK_SHORT; /* The whole blob was not examined */
@@ -242,17 +239,16 @@
239 c = UTF16_SWAP(c);
240 }
241 if( c==0 ){
242 flags |= LOOK_NUL; /* NUL character in a file -> binary */
243 }else if( c=='\r' ){
 
244 if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){
245 flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
246 }
247 }
248 j = (c!='\n');
249 if( !j ) flags |= (LOOK_LONE_LF); /* Found LF as first char */
250 while( !(flags&stopFlags) && ((n-=sizeof(WCHAR_T))>=sizeof(WCHAR_T)) ){
251 int c2 = c;
252 c = *++z;
253 if( bReverse ){
254 c = UTF16_SWAP(c);
@@ -259,24 +255,22 @@
255 }
256 ++j;
257 if( c==0 ){
258 flags |= LOOK_NUL; /* NUL character in a file -> binary */
259 }else if( c=='\n' ){
 
260 if( c2=='\r' ){
261 flags |= (LOOK_CRLF); /* Found LF preceded by CR */
262 }else{
263 flags |= LOOK_LONE_LF;
264 }
265 if( j>UTF16_LENGTH_MASK ){
266 flags |= LOOK_LONG; /* Very long line -> binary */
267 }
268 j = 0;
269 }else if( c=='\r' ){
 
270 if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){
271 flags |= LOOK_LONE_CR; /* Not enough chars or next char not LF */
272 }
273 }
274 }
275 if( n ){
276 flags |= LOOK_SHORT; /* The whole blob was not examined */
277
+13 -12
--- src/main.c
+++ src/main.c
@@ -1111,11 +1111,11 @@
11111111
**
11121112
** Usage: %fossil help COMMAND
11131113
** or: %fossil COMMAND --help
11141114
**
11151115
** Display information on how to use COMMAND. To display a list of
1116
-** available commands one of:
1116
+** available commands use one of:
11171117
**
11181118
** %fossil help Show common commands
11191119
** %fossil help -a|--all Show both common and auxiliary commands
11201120
** %fossil help -t|--test Show test commands only
11211121
** %fossil help -x|--aux Show auxiliary commands only
@@ -1427,11 +1427,12 @@
14271427
**
14281428
** Assume the user-id and group-id of the repository, or if zRepo
14291429
** is a directory, of that directory.
14301430
**
14311431
** The noJail flag means that the chroot jail is not entered. But
1432
-** privileges are still lowered to that of the the user-id and group-id.
1432
+** privileges are still lowered to that of the user-id and group-id
1433
+** of the repository file.
14331434
*/
14341435
static char *enter_chroot_jail(char *zRepo, int noJail){
14351436
#if !defined(_WIN32)
14361437
if( getuid()==0 ){
14371438
int i;
@@ -1534,11 +1535,11 @@
15341535
** and the actual repository is taken from the first element of PATH_INFO.
15351536
**
15361537
** Process the webpage specified by the PATH_INFO or REQUEST_URI
15371538
** environment variable.
15381539
**
1539
-** If the repository is not known, the a search is done through the
1540
+** If the repository is not known, then a search is done through the
15401541
** file hierarchy rooted at g.zRepositoryName for a suitable repository
15411542
** with a name of $prefix.fossil, where $prefix is any prefix of PATH_INFO.
15421543
** Or, if an ordinary file named $prefix is found, and $prefix matches
15431544
** pFileGlob and $prefix does not match "*.fossil*" and the mimetype of
15441545
** $prefix can be determined from its suffix, then the file $prefix is
@@ -2105,12 +2106,12 @@
21052106
/*
21062107
** If g.argv[arg] exists then it is either the name of a repository
21072108
** that will be used by a server, or else it is a directory that
21082109
** contains multiple repositories that can be served. If g.argv[arg]
21092110
** is a directory, the repositories it contains must be named
2110
-** "*.fossil". If g.argv[arg] does not exists, then we must be within
2111
-** a check-out and the repository to be served is the repository of
2111
+** "*.fossil". If g.argv[arg] does not exist, then we must be within
2112
+** an open check-out and the repository serve is the repository of
21122113
** that check-out.
21132114
**
21142115
** Open the repository to be served if it is known. If g.argv[arg] is
21152116
** a directory full of repositories, then set g.zRepositoryName to
21162117
** the name of that directory and the specific repository will be
@@ -2155,11 +2156,11 @@
21552156
/*
21562157
** undocumented format:
21572158
**
21582159
** fossil http INFILE OUTFILE IPADDR ?REPOSITORY?
21592160
**
2160
-** The argv==6 form is used by the win32 server only.
2161
+** The argv==6 form (with no options) is used by the win32 server only.
21612162
**
21622163
** COMMAND: http*
21632164
**
21642165
** Usage: %fossil http ?REPOSITORY? ?OPTIONS?
21652166
**
@@ -2167,12 +2168,12 @@
21672168
** is delivered on stdout. This method is used to launch an HTTP request
21682169
** handler from inetd, for example. The argument is the name of the
21692170
** repository.
21702171
**
21712172
** If REPOSITORY is a directory that contains one or more repositories,
2172
-** either directly in REPOSITORY itself, or in subdirectories, and
2173
-** with names of the form "*.fossil" then the a prefix of the URL pathname
2173
+** either directly in REPOSITORY itself or in subdirectories, and
2174
+** with names of the form "*.fossil" then a prefix of the URL pathname
21742175
** selects from among the various repositories. If the pathname does
21752176
** not select a valid repository and the --notfound option is available,
21762177
** then the server redirects (HTTP code 302) to the URL of --notfound.
21772178
** When REPOSITORY is a directory, the pathname must contain only
21782179
** alphanumerics, "_", "/", "-" and "." and no "-" may occur after a "/"
@@ -2507,13 +2508,13 @@
25072508
zBrowser, zIpAddr, zInitPage);
25082509
}else{
25092510
zBrowserCmd = mprintf("%s http://localhost:%%d/%s &",
25102511
zBrowser, zInitPage);
25112512
}
2512
- if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
2513
- if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
25142513
}
2514
+ if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
2515
+ if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
25152516
db_close(1);
25162517
if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
25172518
fossil_fatal("unable to listen on TCP socket %d", iPort);
25182519
}
25192520
g.sslNotAvailable = 1;
@@ -2540,13 +2541,13 @@
25402541
zBrowser, zIpAddr, zInitPage);
25412542
}else{
25422543
zBrowserCmd = mprintf("%s http://localhost:%%d/%s &",
25432544
zBrowser, zInitPage);
25442545
}
2545
- if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
2546
- if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
25472546
}
2547
+ if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
2548
+ if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
25482549
db_close(1);
25492550
if( allowRepoList ){
25502551
flags |= HTTP_SERVER_REPOLIST;
25512552
}
25522553
if( win32_http_service(iPort, zNotFound, zFileGlob, flags) ){
25532554
--- src/main.c
+++ src/main.c
@@ -1111,11 +1111,11 @@
1111 **
1112 ** Usage: %fossil help COMMAND
1113 ** or: %fossil COMMAND --help
1114 **
1115 ** Display information on how to use COMMAND. To display a list of
1116 ** available commands one of:
1117 **
1118 ** %fossil help Show common commands
1119 ** %fossil help -a|--all Show both common and auxiliary commands
1120 ** %fossil help -t|--test Show test commands only
1121 ** %fossil help -x|--aux Show auxiliary commands only
@@ -1427,11 +1427,12 @@
1427 **
1428 ** Assume the user-id and group-id of the repository, or if zRepo
1429 ** is a directory, of that directory.
1430 **
1431 ** The noJail flag means that the chroot jail is not entered. But
1432 ** privileges are still lowered to that of the the user-id and group-id.
 
1433 */
1434 static char *enter_chroot_jail(char *zRepo, int noJail){
1435 #if !defined(_WIN32)
1436 if( getuid()==0 ){
1437 int i;
@@ -1534,11 +1535,11 @@
1534 ** and the actual repository is taken from the first element of PATH_INFO.
1535 **
1536 ** Process the webpage specified by the PATH_INFO or REQUEST_URI
1537 ** environment variable.
1538 **
1539 ** If the repository is not known, the a search is done through the
1540 ** file hierarchy rooted at g.zRepositoryName for a suitable repository
1541 ** with a name of $prefix.fossil, where $prefix is any prefix of PATH_INFO.
1542 ** Or, if an ordinary file named $prefix is found, and $prefix matches
1543 ** pFileGlob and $prefix does not match "*.fossil*" and the mimetype of
1544 ** $prefix can be determined from its suffix, then the file $prefix is
@@ -2105,12 +2106,12 @@
2105 /*
2106 ** If g.argv[arg] exists then it is either the name of a repository
2107 ** that will be used by a server, or else it is a directory that
2108 ** contains multiple repositories that can be served. If g.argv[arg]
2109 ** is a directory, the repositories it contains must be named
2110 ** "*.fossil". If g.argv[arg] does not exists, then we must be within
2111 ** a check-out and the repository to be served is the repository of
2112 ** that check-out.
2113 **
2114 ** Open the repository to be served if it is known. If g.argv[arg] is
2115 ** a directory full of repositories, then set g.zRepositoryName to
2116 ** the name of that directory and the specific repository will be
@@ -2155,11 +2156,11 @@
2155 /*
2156 ** undocumented format:
2157 **
2158 ** fossil http INFILE OUTFILE IPADDR ?REPOSITORY?
2159 **
2160 ** The argv==6 form is used by the win32 server only.
2161 **
2162 ** COMMAND: http*
2163 **
2164 ** Usage: %fossil http ?REPOSITORY? ?OPTIONS?
2165 **
@@ -2167,12 +2168,12 @@
2167 ** is delivered on stdout. This method is used to launch an HTTP request
2168 ** handler from inetd, for example. The argument is the name of the
2169 ** repository.
2170 **
2171 ** If REPOSITORY is a directory that contains one or more repositories,
2172 ** either directly in REPOSITORY itself, or in subdirectories, and
2173 ** with names of the form "*.fossil" then the a prefix of the URL pathname
2174 ** selects from among the various repositories. If the pathname does
2175 ** not select a valid repository and the --notfound option is available,
2176 ** then the server redirects (HTTP code 302) to the URL of --notfound.
2177 ** When REPOSITORY is a directory, the pathname must contain only
2178 ** alphanumerics, "_", "/", "-" and "." and no "-" may occur after a "/"
@@ -2507,13 +2508,13 @@
2507 zBrowser, zIpAddr, zInitPage);
2508 }else{
2509 zBrowserCmd = mprintf("%s http://localhost:%%d/%s &",
2510 zBrowser, zInitPage);
2511 }
2512 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
2513 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
2514 }
 
 
2515 db_close(1);
2516 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
2517 fossil_fatal("unable to listen on TCP socket %d", iPort);
2518 }
2519 g.sslNotAvailable = 1;
@@ -2540,13 +2541,13 @@
2540 zBrowser, zIpAddr, zInitPage);
2541 }else{
2542 zBrowserCmd = mprintf("%s http://localhost:%%d/%s &",
2543 zBrowser, zInitPage);
2544 }
2545 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
2546 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
2547 }
 
 
2548 db_close(1);
2549 if( allowRepoList ){
2550 flags |= HTTP_SERVER_REPOLIST;
2551 }
2552 if( win32_http_service(iPort, zNotFound, zFileGlob, flags) ){
2553
--- src/main.c
+++ src/main.c
@@ -1111,11 +1111,11 @@
1111 **
1112 ** Usage: %fossil help COMMAND
1113 ** or: %fossil COMMAND --help
1114 **
1115 ** Display information on how to use COMMAND. To display a list of
1116 ** available commands use one of:
1117 **
1118 ** %fossil help Show common commands
1119 ** %fossil help -a|--all Show both common and auxiliary commands
1120 ** %fossil help -t|--test Show test commands only
1121 ** %fossil help -x|--aux Show auxiliary commands only
@@ -1427,11 +1427,12 @@
1427 **
1428 ** Assume the user-id and group-id of the repository, or if zRepo
1429 ** is a directory, of that directory.
1430 **
1431 ** The noJail flag means that the chroot jail is not entered. But
1432 ** privileges are still lowered to that of the user-id and group-id
1433 ** of the repository file.
1434 */
1435 static char *enter_chroot_jail(char *zRepo, int noJail){
1436 #if !defined(_WIN32)
1437 if( getuid()==0 ){
1438 int i;
@@ -1534,11 +1535,11 @@
1535 ** and the actual repository is taken from the first element of PATH_INFO.
1536 **
1537 ** Process the webpage specified by the PATH_INFO or REQUEST_URI
1538 ** environment variable.
1539 **
1540 ** If the repository is not known, then a search is done through the
1541 ** file hierarchy rooted at g.zRepositoryName for a suitable repository
1542 ** with a name of $prefix.fossil, where $prefix is any prefix of PATH_INFO.
1543 ** Or, if an ordinary file named $prefix is found, and $prefix matches
1544 ** pFileGlob and $prefix does not match "*.fossil*" and the mimetype of
1545 ** $prefix can be determined from its suffix, then the file $prefix is
@@ -2105,12 +2106,12 @@
2106 /*
2107 ** If g.argv[arg] exists then it is either the name of a repository
2108 ** that will be used by a server, or else it is a directory that
2109 ** contains multiple repositories that can be served. If g.argv[arg]
2110 ** is a directory, the repositories it contains must be named
2111 ** "*.fossil". If g.argv[arg] does not exist, then we must be within
2112 ** an open check-out and the repository serve is the repository of
2113 ** that check-out.
2114 **
2115 ** Open the repository to be served if it is known. If g.argv[arg] is
2116 ** a directory full of repositories, then set g.zRepositoryName to
2117 ** the name of that directory and the specific repository will be
@@ -2155,11 +2156,11 @@
2156 /*
2157 ** undocumented format:
2158 **
2159 ** fossil http INFILE OUTFILE IPADDR ?REPOSITORY?
2160 **
2161 ** The argv==6 form (with no options) is used by the win32 server only.
2162 **
2163 ** COMMAND: http*
2164 **
2165 ** Usage: %fossil http ?REPOSITORY? ?OPTIONS?
2166 **
@@ -2167,12 +2168,12 @@
2168 ** is delivered on stdout. This method is used to launch an HTTP request
2169 ** handler from inetd, for example. The argument is the name of the
2170 ** repository.
2171 **
2172 ** If REPOSITORY is a directory that contains one or more repositories,
2173 ** either directly in REPOSITORY itself or in subdirectories, and
2174 ** with names of the form "*.fossil" then a prefix of the URL pathname
2175 ** selects from among the various repositories. If the pathname does
2176 ** not select a valid repository and the --notfound option is available,
2177 ** then the server redirects (HTTP code 302) to the URL of --notfound.
2178 ** When REPOSITORY is a directory, the pathname must contain only
2179 ** alphanumerics, "_", "/", "-" and "." and no "-" may occur after a "/"
@@ -2507,13 +2508,13 @@
2508 zBrowser, zIpAddr, zInitPage);
2509 }else{
2510 zBrowserCmd = mprintf("%s http://localhost:%%d/%s &",
2511 zBrowser, zInitPage);
2512 }
 
 
2513 }
2514 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
2515 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
2516 db_close(1);
2517 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
2518 fossil_fatal("unable to listen on TCP socket %d", iPort);
2519 }
2520 g.sslNotAvailable = 1;
@@ -2540,13 +2541,13 @@
2541 zBrowser, zIpAddr, zInitPage);
2542 }else{
2543 zBrowserCmd = mprintf("%s http://localhost:%%d/%s &",
2544 zBrowser, zInitPage);
2545 }
 
 
2546 }
2547 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
2548 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
2549 db_close(1);
2550 if( allowRepoList ){
2551 flags |= HTTP_SERVER_REPOLIST;
2552 }
2553 if( win32_http_service(iPort, zNotFound, zFileGlob, flags) ){
2554
+157 -24
--- src/manifest.c
+++ src/manifest.c
@@ -380,13 +380,13 @@
380380
** if that is not the case for this artifact.
381381
*/
382382
if( !isRepeat ) g.parseCnt[0]++;
383383
z = blob_materialize(pContent);
384384
n = blob_size(pContent);
385
- if( pErr && (n<=0 || z[n-1]!='\n') ){
385
+ if( n<=0 || z[n-1]!='\n' ){
386386
blob_reset(pContent);
387
- blob_append(pErr, n ? "not terminated with \\n" : "zero-length", -1);
387
+ blob_appendf(pErr, "%s", n ? "not terminated with \\n" : "zero-length");
388388
return 0;
389389
}
390390
391391
/* Strip off the PGP signature if there is one.
392392
*/
@@ -1185,10 +1185,15 @@
11851185
}
11861186
11871187
/*
11881188
** Add a single entry to the mlink table. Also add the filename to
11891189
** the filename table if it is not there already.
1190
+**
1191
+** An mlink entry is always created if isPrimary is true. But if
1192
+** isPrimary is false (meaning that pmid is a merge parent of mid)
1193
+** then the mlink entry is only created if there is already an mlink
1194
+** from primary parent for the same file.
11901195
*/
11911196
static void add_one_mlink(
11921197
int pmid, /* The parent manifest */
11931198
const char *zFromUuid, /* UUID for content in parent */
11941199
int mid, /* The record ID of the manifest */
@@ -1198,11 +1203,12 @@
11981203
int isPublic, /* True if mid is not a private manifest */
11991204
int isPrimary, /* pmid is the primary parent of mid */
12001205
int mperm /* 1: exec, 2: symlink */
12011206
){
12021207
int fnid, pfnid, pid, fid;
1203
- static Stmt s1;
1208
+ int doInsert;
1209
+ static Stmt s1, s2;
12041210
12051211
fnid = filename_to_fnid(zFilename);
12061212
if( zPrior==0 ){
12071213
pfnid = 0;
12081214
}else{
@@ -1217,23 +1223,36 @@
12171223
fid = 0;
12181224
}else{
12191225
fid = uuid_to_rid(zToUuid, 1);
12201226
if( isPublic ) content_make_public(fid);
12211227
}
1222
- db_static_prepare(&s1,
1223
- "INSERT INTO mlink(mid,fid,pmid,pid,fnid,pfnid,mperm,isaux)"
1224
- "VALUES(:m,:f,:pm,:p,:n,:pfn,:mp,:isaux)"
1225
- );
1226
- db_bind_int(&s1, ":m", mid);
1227
- db_bind_int(&s1, ":f", fid);
1228
- db_bind_int(&s1, ":pm", pmid);
1229
- db_bind_int(&s1, ":p", pid);
1230
- db_bind_int(&s1, ":n", fnid);
1231
- db_bind_int(&s1, ":pfn", pfnid);
1232
- db_bind_int(&s1, ":mp", mperm);
1233
- db_bind_int(&s1, ":isaux", isPrimary==0);
1234
- db_exec(&s1);
1228
+ if( isPrimary ){
1229
+ doInsert = 1;
1230
+ }else{
1231
+ db_static_prepare(&s2,
1232
+ "SELECT 1 FROM mlink WHERE mid=:m AND fnid=:n AND NOT isaux"
1233
+ );
1234
+ db_bind_int(&s2, ":m", mid);
1235
+ db_bind_int(&s2, ":n", fnid);
1236
+ doInsert = db_step(&s2)==SQLITE_ROW;
1237
+ db_reset(&s2);
1238
+ }
1239
+ if( doInsert ){
1240
+ db_static_prepare(&s1,
1241
+ "INSERT INTO mlink(mid,fid,pmid,pid,fnid,pfnid,mperm,isaux)"
1242
+ "VALUES(:m,:f,:pm,:p,:n,:pfn,:mp,:isaux)"
1243
+ );
1244
+ db_bind_int(&s1, ":m", mid);
1245
+ db_bind_int(&s1, ":f", fid);
1246
+ db_bind_int(&s1, ":pm", pmid);
1247
+ db_bind_int(&s1, ":p", pid);
1248
+ db_bind_int(&s1, ":n", fnid);
1249
+ db_bind_int(&s1, ":pfn", pfnid);
1250
+ db_bind_int(&s1, ":mp", mperm);
1251
+ db_bind_int(&s1, ":isaux", isPrimary==0);
1252
+ db_exec(&s1);
1253
+ }
12351254
if( pid && fid ){
12361255
content_deltify(pid, fid, 0);
12371256
}
12381257
}
12391258
@@ -1346,15 +1365,24 @@
13461365
**
13471366
** Deleted files have mlink.fid=0.
13481367
** Added files have mlink.pid=0.
13491368
** File added by merge have mlink.pid=-1
13501369
** Edited files have both mlink.pid!=0 and mlink.fid!=0
1370
+**
1371
+** Many mlink entries for merge parents will only be added if another mlink
1372
+** entry already exists for the same file from the primary parent. Therefore,
1373
+** to ensure that all merge-parent mlink entries are properly created:
1374
+**
1375
+** (1) Make this routine a no-op if pParent is a merge parent and the
1376
+** primary parent is a phantom.
1377
+** (2) Invoke this routine recursively for merge-parents if pParent is the
1378
+** primary parent.
13511379
*/
13521380
static void add_mlink(
1353
- int pmid, Manifest *pParent, /* Parent check-in */
1354
- int mid, Manifest *pChild, /* The child check-in */
1355
- int isPrim /* TRUE if pmid is the primary parent of mid */
1381
+ int pmid, Manifest *pParent, /* Parent check-in */
1382
+ int mid, Manifest *pChild, /* The child check-in */
1383
+ int isPrim /* TRUE if pmid is the primary parent of mid */
13561384
){
13571385
Blob otherContent;
13581386
int otherRid;
13591387
int i, rc;
13601388
ManifestFile *pChildFile, *pParentFile;
@@ -1392,10 +1420,23 @@
13921420
if( fetch_baseline(pParent, 0) || fetch_baseline(pChild, 0) ){
13931421
manifest_destroy(*ppOther);
13941422
return;
13951423
}
13961424
isPublic = !content_is_private(mid);
1425
+
1426
+ /* If pParent is not the primary parent of pChild, and the primary
1427
+ ** parent of pChild is a phantom, then abort this routine without
1428
+ ** doing any work. The mlink entries will be computed when the
1429
+ ** primary parent dephantomizes.
1430
+ */
1431
+ if( !isPrim && otherRid==mid
1432
+ && !db_exists("SELECT 1 FROM blob WHERE uuid=%Q AND size>0",
1433
+ pChild->azParent[0])
1434
+ ){
1435
+ manifest_cache_insert(*ppOther);
1436
+ return;
1437
+ }
13971438
13981439
/* Try to make the parent manifest a delta from the child, if that
13991440
** is an appropriate thing to do. For a new baseline, make the
14001441
** previous baseline a delta from the current baseline.
14011442
*/
@@ -1489,10 +1530,21 @@
14891530
isPublic, isPrim, 0);
14901531
}
14911532
}
14921533
}
14931534
manifest_cache_insert(*ppOther);
1535
+
1536
+ /* If pParent is the primary parent of pChild, also run this analysis
1537
+ ** for all merge parents of pChild
1538
+ */
1539
+ if( isPrim ){
1540
+ for(i=1; i<pChild->nParent; i++){
1541
+ pmid = uuid_to_rid(pChild->azParent[i], 0);
1542
+ if( pmid<=0 ) continue;
1543
+ add_mlink(pmid, 0, mid, pChild, 0);
1544
+ }
1545
+ }
14941546
}
14951547
14961548
/*
14971549
** Setup to do multiple manifest_crosslink() calls.
14981550
** This is only required if processing ticket changes.
@@ -1798,13 +1850,13 @@
17981850
int pid = uuid_to_rid(p->azParent[i], 1);
17991851
db_multi_exec(
18001852
"INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
18011853
"VALUES(%d, %d, %d, %.17g, %s)",
18021854
pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
1803
- add_mlink(pid, 0, rid, p, i==0);
18041855
if( i==0 ) parentid = pid;
18051856
}
1857
+ add_mlink(parentid, 0, rid, p, 1);
18061858
if( p->nParent>1 ){
18071859
/* Change MLINK.PID from 0 to -1 for files that are added by merge. */
18081860
db_multi_exec(
18091861
"UPDATE mlink SET pid=-1"
18101862
" WHERE mid=%d"
@@ -1956,10 +2008,11 @@
19562008
char *zTag = mprintf("event-%s", p->zEventId);
19572009
int tagid = tag_findid(zTag, 1);
19582010
int prior, subsequent;
19592011
int nWiki;
19602012
char zLength[40];
2013
+ Stmt qatt;
19612014
while( fossil_isspace(p->zWiki[0]) ) p->zWiki++;
19622015
nWiki = strlen(p->zWiki);
19632016
sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki);
19642017
tag_insert(zTag, 1, zLength, rid, p->rDate, rid);
19652018
fossil_free(zTag);
@@ -1997,26 +2050,95 @@
19972050
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
19982051
p->rEventDate, rid, tagid, p->zUser, p->zComment,
19992052
TAG_BGCOLOR, rid
20002053
);
20012054
}
2055
+ /* Locate and update comment for any attachments */
2056
+ db_prepare(&qatt,
2057
+ "SELECT attachid, src, target, filename FROM attachment"
2058
+ " WHERE target=%Q",
2059
+ p->zEventId
2060
+ );
2061
+ while( db_step(&qatt)==SQLITE_ROW ){
2062
+ const char *zAttachId = db_column_text(&qatt, 0);
2063
+ const char *zSrc = db_column_text(&qatt, 1);
2064
+ const char *zTarget = db_column_text(&qatt, 2);
2065
+ const char *zName = db_column_text(&qatt, 3);
2066
+ const char isAdd = (zSrc && zSrc[0]) ? 1 : 0;
2067
+ char *zComment;
2068
+ if( isAdd ){
2069
+ zComment = mprintf(
2070
+ "Add attachment [/artifact/%!S|%h] to"
2071
+ " tech note [/technote/%h|%.10h]",
2072
+ zSrc, zName, zTarget, zTarget);
2073
+ }else{
2074
+ zComment = mprintf("Delete attachment \"%h\" from tech note [%.10h]",
2075
+ zName, zTarget);
2076
+ }
2077
+ db_multi_exec("UPDATE event SET comment=%Q, type='e'"
2078
+ " WHERE objid=%Q",
2079
+ zComment, zAttachId);
2080
+ fossil_free(zComment);
2081
+ }
2082
+ db_finalize(&qatt);
20022083
}
20032084
if( p->type==CFTYPE_TICKET ){
20042085
char *zTag;
2086
+ Stmt qatt;
20052087
assert( manifest_crosslink_busy==1 );
20062088
zTag = mprintf("tkt-%s", p->zTicketUuid);
20072089
tag_insert(zTag, 1, 0, rid, p->rDate, rid);
20082090
fossil_free(zTag);
20092091
db_multi_exec("INSERT OR IGNORE INTO pending_tkt VALUES(%Q)",
20102092
p->zTicketUuid);
2093
+ /* Locate and update comment for any attachments */
2094
+ db_prepare(&qatt,
2095
+ "SELECT attachid, src, target, filename FROM attachment"
2096
+ " WHERE target=%Q",
2097
+ p->zTicketUuid
2098
+ );
2099
+ while( db_step(&qatt)==SQLITE_ROW ){
2100
+ const char *zAttachId = db_column_text(&qatt, 0);
2101
+ const char *zSrc = db_column_text(&qatt, 1);
2102
+ const char *zTarget = db_column_text(&qatt, 2);
2103
+ const char *zName = db_column_text(&qatt, 3);
2104
+ const char isAdd = (zSrc && zSrc[0]) ? 1 : 0;
2105
+ char *zComment;
2106
+ if( isAdd ){
2107
+ zComment = mprintf(
2108
+ "Add attachment [/artifact/%!S|%h] to ticket [%!S|%S]",
2109
+ zSrc, zName, zTarget, zTarget);
2110
+ }else{
2111
+ zComment = mprintf("Delete attachment \"%h\" from ticket [%!S|%S]",
2112
+ zName, zTarget, zTarget);
2113
+ }
2114
+ db_multi_exec("UPDATE event SET comment=%Q, type='t'"
2115
+ " WHERE objid=%Q",
2116
+ zComment, zAttachId);
2117
+ fossil_free(zComment);
2118
+ }
2119
+ db_finalize(&qatt);
20112120
}
20122121
if( p->type==CFTYPE_ATTACHMENT ){
20132122
char *zComment = 0;
20142123
const char isAdd = (p->zAttachSrc && p->zAttachSrc[0]) ? 1 : 0;
2015
- const char attachToType = fossil_is_uuid(p->zAttachTarget)
2016
- ? 't' /* attach to ticket */
2017
- : 'w' /* attach to wiki page */;
2124
+ /* We assume that we're attaching to a wiki page until we
2125
+ ** prove otherwise (which could on a later artifact if we
2126
+ ** process the attachment artifact before the artifact to
2127
+ ** which it is attached!) */
2128
+ char attachToType = 'w';
2129
+ if( fossil_is_uuid(p->zAttachTarget) ){
2130
+ if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
2131
+ p->zAttachTarget)
2132
+ ){
2133
+ attachToType = 't'; /* Attaching to known ticket */
2134
+ }else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",
2135
+ p->zAttachTarget)
2136
+ ){
2137
+ attachToType = 'e'; /* Attaching to known tech note */
2138
+ }
2139
+ }
20182140
db_multi_exec(
20192141
"INSERT INTO attachment(attachid, mtime, src, target,"
20202142
"filename, comment, user)"
20212143
"VALUES(%d,%.17g,%Q,%Q,%Q,%Q,%Q);",
20222144
rid, p->rDate, p->zAttachSrc, p->zAttachTarget, p->zAttachName,
@@ -2037,10 +2159,19 @@
20372159
p->zAttachSrc, p->zAttachName, p->zAttachTarget);
20382160
}else{
20392161
zComment = mprintf("Delete attachment \"%h\" from wiki page [%h]",
20402162
p->zAttachName, p->zAttachTarget);
20412163
}
2164
+ }else if( 'e' == attachToType ){
2165
+ if( isAdd ){
2166
+ zComment = mprintf(
2167
+ "Add attachment [/artifact/%!S|%h] to tech note [/technote/%h|%.10h]",
2168
+ p->zAttachSrc, p->zAttachName, p->zAttachTarget, p->zAttachTarget);
2169
+ }else{
2170
+ zComment = mprintf("Delete attachment \"%h\" from tech note [%.10h]",
2171
+ p->zAttachName, p->zAttachTarget);
2172
+ }
20422173
}else{
20432174
if( isAdd ){
20442175
zComment = mprintf(
20452176
"Add attachment [/artifact/%!S|%h] to ticket [%!S|%S]",
20462177
p->zAttachSrc, p->zAttachName, p->zAttachTarget, p->zAttachTarget);
@@ -2110,11 +2241,13 @@
21102241
continue;
21112242
}else if( strcmp(zName, "+date")==0 ){
21122243
blob_appendf(&comment, " Timestamp %h.", zValue);
21132244
continue;
21142245
}else if( memcmp(zName, "-sym-",5)==0 ){
2115
- if( !branchMove ) blob_appendf(&comment, " Cancel tag \"%h\"", &zName[5]);
2246
+ if( !branchMove ){
2247
+ blob_appendf(&comment, " Cancel tag \"%h\"", &zName[5]);
2248
+ }
21162249
}else if( memcmp(zName, "*sym-",5)==0 ){
21172250
if( !branchMove ){
21182251
blob_appendf(&comment, " Add propagating tag \"%h\"", &zName[5]);
21192252
}
21202253
}else if( memcmp(zName, "+sym-",5)==0 ){
21212254
--- src/manifest.c
+++ src/manifest.c
@@ -380,13 +380,13 @@
380 ** if that is not the case for this artifact.
381 */
382 if( !isRepeat ) g.parseCnt[0]++;
383 z = blob_materialize(pContent);
384 n = blob_size(pContent);
385 if( pErr && (n<=0 || z[n-1]!='\n') ){
386 blob_reset(pContent);
387 blob_append(pErr, n ? "not terminated with \\n" : "zero-length", -1);
388 return 0;
389 }
390
391 /* Strip off the PGP signature if there is one.
392 */
@@ -1185,10 +1185,15 @@
1185 }
1186
1187 /*
1188 ** Add a single entry to the mlink table. Also add the filename to
1189 ** the filename table if it is not there already.
 
 
 
 
 
1190 */
1191 static void add_one_mlink(
1192 int pmid, /* The parent manifest */
1193 const char *zFromUuid, /* UUID for content in parent */
1194 int mid, /* The record ID of the manifest */
@@ -1198,11 +1203,12 @@
1198 int isPublic, /* True if mid is not a private manifest */
1199 int isPrimary, /* pmid is the primary parent of mid */
1200 int mperm /* 1: exec, 2: symlink */
1201 ){
1202 int fnid, pfnid, pid, fid;
1203 static Stmt s1;
 
1204
1205 fnid = filename_to_fnid(zFilename);
1206 if( zPrior==0 ){
1207 pfnid = 0;
1208 }else{
@@ -1217,23 +1223,36 @@
1217 fid = 0;
1218 }else{
1219 fid = uuid_to_rid(zToUuid, 1);
1220 if( isPublic ) content_make_public(fid);
1221 }
1222 db_static_prepare(&s1,
1223 "INSERT INTO mlink(mid,fid,pmid,pid,fnid,pfnid,mperm,isaux)"
1224 "VALUES(:m,:f,:pm,:p,:n,:pfn,:mp,:isaux)"
1225 );
1226 db_bind_int(&s1, ":m", mid);
1227 db_bind_int(&s1, ":f", fid);
1228 db_bind_int(&s1, ":pm", pmid);
1229 db_bind_int(&s1, ":p", pid);
1230 db_bind_int(&s1, ":n", fnid);
1231 db_bind_int(&s1, ":pfn", pfnid);
1232 db_bind_int(&s1, ":mp", mperm);
1233 db_bind_int(&s1, ":isaux", isPrimary==0);
1234 db_exec(&s1);
 
 
 
 
 
 
 
 
 
 
 
 
 
1235 if( pid && fid ){
1236 content_deltify(pid, fid, 0);
1237 }
1238 }
1239
@@ -1346,15 +1365,24 @@
1346 **
1347 ** Deleted files have mlink.fid=0.
1348 ** Added files have mlink.pid=0.
1349 ** File added by merge have mlink.pid=-1
1350 ** Edited files have both mlink.pid!=0 and mlink.fid!=0
 
 
 
 
 
 
 
 
 
1351 */
1352 static void add_mlink(
1353 int pmid, Manifest *pParent, /* Parent check-in */
1354 int mid, Manifest *pChild, /* The child check-in */
1355 int isPrim /* TRUE if pmid is the primary parent of mid */
1356 ){
1357 Blob otherContent;
1358 int otherRid;
1359 int i, rc;
1360 ManifestFile *pChildFile, *pParentFile;
@@ -1392,10 +1420,23 @@
1392 if( fetch_baseline(pParent, 0) || fetch_baseline(pChild, 0) ){
1393 manifest_destroy(*ppOther);
1394 return;
1395 }
1396 isPublic = !content_is_private(mid);
 
 
 
 
 
 
 
 
 
 
 
 
 
1397
1398 /* Try to make the parent manifest a delta from the child, if that
1399 ** is an appropriate thing to do. For a new baseline, make the
1400 ** previous baseline a delta from the current baseline.
1401 */
@@ -1489,10 +1530,21 @@
1489 isPublic, isPrim, 0);
1490 }
1491 }
1492 }
1493 manifest_cache_insert(*ppOther);
 
 
 
 
 
 
 
 
 
 
 
1494 }
1495
1496 /*
1497 ** Setup to do multiple manifest_crosslink() calls.
1498 ** This is only required if processing ticket changes.
@@ -1798,13 +1850,13 @@
1798 int pid = uuid_to_rid(p->azParent[i], 1);
1799 db_multi_exec(
1800 "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
1801 "VALUES(%d, %d, %d, %.17g, %s)",
1802 pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
1803 add_mlink(pid, 0, rid, p, i==0);
1804 if( i==0 ) parentid = pid;
1805 }
 
1806 if( p->nParent>1 ){
1807 /* Change MLINK.PID from 0 to -1 for files that are added by merge. */
1808 db_multi_exec(
1809 "UPDATE mlink SET pid=-1"
1810 " WHERE mid=%d"
@@ -1956,10 +2008,11 @@
1956 char *zTag = mprintf("event-%s", p->zEventId);
1957 int tagid = tag_findid(zTag, 1);
1958 int prior, subsequent;
1959 int nWiki;
1960 char zLength[40];
 
1961 while( fossil_isspace(p->zWiki[0]) ) p->zWiki++;
1962 nWiki = strlen(p->zWiki);
1963 sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki);
1964 tag_insert(zTag, 1, zLength, rid, p->rDate, rid);
1965 fossil_free(zTag);
@@ -1997,26 +2050,95 @@
1997 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
1998 p->rEventDate, rid, tagid, p->zUser, p->zComment,
1999 TAG_BGCOLOR, rid
2000 );
2001 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2002 }
2003 if( p->type==CFTYPE_TICKET ){
2004 char *zTag;
 
2005 assert( manifest_crosslink_busy==1 );
2006 zTag = mprintf("tkt-%s", p->zTicketUuid);
2007 tag_insert(zTag, 1, 0, rid, p->rDate, rid);
2008 fossil_free(zTag);
2009 db_multi_exec("INSERT OR IGNORE INTO pending_tkt VALUES(%Q)",
2010 p->zTicketUuid);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2011 }
2012 if( p->type==CFTYPE_ATTACHMENT ){
2013 char *zComment = 0;
2014 const char isAdd = (p->zAttachSrc && p->zAttachSrc[0]) ? 1 : 0;
2015 const char attachToType = fossil_is_uuid(p->zAttachTarget)
2016 ? 't' /* attach to ticket */
2017 : 'w' /* attach to wiki page */;
 
 
 
 
 
 
 
 
 
 
 
 
 
2018 db_multi_exec(
2019 "INSERT INTO attachment(attachid, mtime, src, target,"
2020 "filename, comment, user)"
2021 "VALUES(%d,%.17g,%Q,%Q,%Q,%Q,%Q);",
2022 rid, p->rDate, p->zAttachSrc, p->zAttachTarget, p->zAttachName,
@@ -2037,10 +2159,19 @@
2037 p->zAttachSrc, p->zAttachName, p->zAttachTarget);
2038 }else{
2039 zComment = mprintf("Delete attachment \"%h\" from wiki page [%h]",
2040 p->zAttachName, p->zAttachTarget);
2041 }
 
 
 
 
 
 
 
 
 
2042 }else{
2043 if( isAdd ){
2044 zComment = mprintf(
2045 "Add attachment [/artifact/%!S|%h] to ticket [%!S|%S]",
2046 p->zAttachSrc, p->zAttachName, p->zAttachTarget, p->zAttachTarget);
@@ -2110,11 +2241,13 @@
2110 continue;
2111 }else if( strcmp(zName, "+date")==0 ){
2112 blob_appendf(&comment, " Timestamp %h.", zValue);
2113 continue;
2114 }else if( memcmp(zName, "-sym-",5)==0 ){
2115 if( !branchMove ) blob_appendf(&comment, " Cancel tag \"%h\"", &zName[5]);
 
 
2116 }else if( memcmp(zName, "*sym-",5)==0 ){
2117 if( !branchMove ){
2118 blob_appendf(&comment, " Add propagating tag \"%h\"", &zName[5]);
2119 }
2120 }else if( memcmp(zName, "+sym-",5)==0 ){
2121
--- src/manifest.c
+++ src/manifest.c
@@ -380,13 +380,13 @@
380 ** if that is not the case for this artifact.
381 */
382 if( !isRepeat ) g.parseCnt[0]++;
383 z = blob_materialize(pContent);
384 n = blob_size(pContent);
385 if( n<=0 || z[n-1]!='\n' ){
386 blob_reset(pContent);
387 blob_appendf(pErr, "%s", n ? "not terminated with \\n" : "zero-length");
388 return 0;
389 }
390
391 /* Strip off the PGP signature if there is one.
392 */
@@ -1185,10 +1185,15 @@
1185 }
1186
1187 /*
1188 ** Add a single entry to the mlink table. Also add the filename to
1189 ** the filename table if it is not there already.
1190 **
1191 ** An mlink entry is always created if isPrimary is true. But if
1192 ** isPrimary is false (meaning that pmid is a merge parent of mid)
1193 ** then the mlink entry is only created if there is already an mlink
1194 ** from primary parent for the same file.
1195 */
1196 static void add_one_mlink(
1197 int pmid, /* The parent manifest */
1198 const char *zFromUuid, /* UUID for content in parent */
1199 int mid, /* The record ID of the manifest */
@@ -1198,11 +1203,12 @@
1203 int isPublic, /* True if mid is not a private manifest */
1204 int isPrimary, /* pmid is the primary parent of mid */
1205 int mperm /* 1: exec, 2: symlink */
1206 ){
1207 int fnid, pfnid, pid, fid;
1208 int doInsert;
1209 static Stmt s1, s2;
1210
1211 fnid = filename_to_fnid(zFilename);
1212 if( zPrior==0 ){
1213 pfnid = 0;
1214 }else{
@@ -1217,23 +1223,36 @@
1223 fid = 0;
1224 }else{
1225 fid = uuid_to_rid(zToUuid, 1);
1226 if( isPublic ) content_make_public(fid);
1227 }
1228 if( isPrimary ){
1229 doInsert = 1;
1230 }else{
1231 db_static_prepare(&s2,
1232 "SELECT 1 FROM mlink WHERE mid=:m AND fnid=:n AND NOT isaux"
1233 );
1234 db_bind_int(&s2, ":m", mid);
1235 db_bind_int(&s2, ":n", fnid);
1236 doInsert = db_step(&s2)==SQLITE_ROW;
1237 db_reset(&s2);
1238 }
1239 if( doInsert ){
1240 db_static_prepare(&s1,
1241 "INSERT INTO mlink(mid,fid,pmid,pid,fnid,pfnid,mperm,isaux)"
1242 "VALUES(:m,:f,:pm,:p,:n,:pfn,:mp,:isaux)"
1243 );
1244 db_bind_int(&s1, ":m", mid);
1245 db_bind_int(&s1, ":f", fid);
1246 db_bind_int(&s1, ":pm", pmid);
1247 db_bind_int(&s1, ":p", pid);
1248 db_bind_int(&s1, ":n", fnid);
1249 db_bind_int(&s1, ":pfn", pfnid);
1250 db_bind_int(&s1, ":mp", mperm);
1251 db_bind_int(&s1, ":isaux", isPrimary==0);
1252 db_exec(&s1);
1253 }
1254 if( pid && fid ){
1255 content_deltify(pid, fid, 0);
1256 }
1257 }
1258
@@ -1346,15 +1365,24 @@
1365 **
1366 ** Deleted files have mlink.fid=0.
1367 ** Added files have mlink.pid=0.
1368 ** File added by merge have mlink.pid=-1
1369 ** Edited files have both mlink.pid!=0 and mlink.fid!=0
1370 **
1371 ** Many mlink entries for merge parents will only be added if another mlink
1372 ** entry already exists for the same file from the primary parent. Therefore,
1373 ** to ensure that all merge-parent mlink entries are properly created:
1374 **
1375 ** (1) Make this routine a no-op if pParent is a merge parent and the
1376 ** primary parent is a phantom.
1377 ** (2) Invoke this routine recursively for merge-parents if pParent is the
1378 ** primary parent.
1379 */
1380 static void add_mlink(
1381 int pmid, Manifest *pParent, /* Parent check-in */
1382 int mid, Manifest *pChild, /* The child check-in */
1383 int isPrim /* TRUE if pmid is the primary parent of mid */
1384 ){
1385 Blob otherContent;
1386 int otherRid;
1387 int i, rc;
1388 ManifestFile *pChildFile, *pParentFile;
@@ -1392,10 +1420,23 @@
1420 if( fetch_baseline(pParent, 0) || fetch_baseline(pChild, 0) ){
1421 manifest_destroy(*ppOther);
1422 return;
1423 }
1424 isPublic = !content_is_private(mid);
1425
1426 /* If pParent is not the primary parent of pChild, and the primary
1427 ** parent of pChild is a phantom, then abort this routine without
1428 ** doing any work. The mlink entries will be computed when the
1429 ** primary parent dephantomizes.
1430 */
1431 if( !isPrim && otherRid==mid
1432 && !db_exists("SELECT 1 FROM blob WHERE uuid=%Q AND size>0",
1433 pChild->azParent[0])
1434 ){
1435 manifest_cache_insert(*ppOther);
1436 return;
1437 }
1438
1439 /* Try to make the parent manifest a delta from the child, if that
1440 ** is an appropriate thing to do. For a new baseline, make the
1441 ** previous baseline a delta from the current baseline.
1442 */
@@ -1489,10 +1530,21 @@
1530 isPublic, isPrim, 0);
1531 }
1532 }
1533 }
1534 manifest_cache_insert(*ppOther);
1535
1536 /* If pParent is the primary parent of pChild, also run this analysis
1537 ** for all merge parents of pChild
1538 */
1539 if( isPrim ){
1540 for(i=1; i<pChild->nParent; i++){
1541 pmid = uuid_to_rid(pChild->azParent[i], 0);
1542 if( pmid<=0 ) continue;
1543 add_mlink(pmid, 0, mid, pChild, 0);
1544 }
1545 }
1546 }
1547
1548 /*
1549 ** Setup to do multiple manifest_crosslink() calls.
1550 ** This is only required if processing ticket changes.
@@ -1798,13 +1850,13 @@
1850 int pid = uuid_to_rid(p->azParent[i], 1);
1851 db_multi_exec(
1852 "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
1853 "VALUES(%d, %d, %d, %.17g, %s)",
1854 pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
 
1855 if( i==0 ) parentid = pid;
1856 }
1857 add_mlink(parentid, 0, rid, p, 1);
1858 if( p->nParent>1 ){
1859 /* Change MLINK.PID from 0 to -1 for files that are added by merge. */
1860 db_multi_exec(
1861 "UPDATE mlink SET pid=-1"
1862 " WHERE mid=%d"
@@ -1956,10 +2008,11 @@
2008 char *zTag = mprintf("event-%s", p->zEventId);
2009 int tagid = tag_findid(zTag, 1);
2010 int prior, subsequent;
2011 int nWiki;
2012 char zLength[40];
2013 Stmt qatt;
2014 while( fossil_isspace(p->zWiki[0]) ) p->zWiki++;
2015 nWiki = strlen(p->zWiki);
2016 sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki);
2017 tag_insert(zTag, 1, zLength, rid, p->rDate, rid);
2018 fossil_free(zTag);
@@ -1997,26 +2050,95 @@
2050 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
2051 p->rEventDate, rid, tagid, p->zUser, p->zComment,
2052 TAG_BGCOLOR, rid
2053 );
2054 }
2055 /* Locate and update comment for any attachments */
2056 db_prepare(&qatt,
2057 "SELECT attachid, src, target, filename FROM attachment"
2058 " WHERE target=%Q",
2059 p->zEventId
2060 );
2061 while( db_step(&qatt)==SQLITE_ROW ){
2062 const char *zAttachId = db_column_text(&qatt, 0);
2063 const char *zSrc = db_column_text(&qatt, 1);
2064 const char *zTarget = db_column_text(&qatt, 2);
2065 const char *zName = db_column_text(&qatt, 3);
2066 const char isAdd = (zSrc && zSrc[0]) ? 1 : 0;
2067 char *zComment;
2068 if( isAdd ){
2069 zComment = mprintf(
2070 "Add attachment [/artifact/%!S|%h] to"
2071 " tech note [/technote/%h|%.10h]",
2072 zSrc, zName, zTarget, zTarget);
2073 }else{
2074 zComment = mprintf("Delete attachment \"%h\" from tech note [%.10h]",
2075 zName, zTarget);
2076 }
2077 db_multi_exec("UPDATE event SET comment=%Q, type='e'"
2078 " WHERE objid=%Q",
2079 zComment, zAttachId);
2080 fossil_free(zComment);
2081 }
2082 db_finalize(&qatt);
2083 }
2084 if( p->type==CFTYPE_TICKET ){
2085 char *zTag;
2086 Stmt qatt;
2087 assert( manifest_crosslink_busy==1 );
2088 zTag = mprintf("tkt-%s", p->zTicketUuid);
2089 tag_insert(zTag, 1, 0, rid, p->rDate, rid);
2090 fossil_free(zTag);
2091 db_multi_exec("INSERT OR IGNORE INTO pending_tkt VALUES(%Q)",
2092 p->zTicketUuid);
2093 /* Locate and update comment for any attachments */
2094 db_prepare(&qatt,
2095 "SELECT attachid, src, target, filename FROM attachment"
2096 " WHERE target=%Q",
2097 p->zTicketUuid
2098 );
2099 while( db_step(&qatt)==SQLITE_ROW ){
2100 const char *zAttachId = db_column_text(&qatt, 0);
2101 const char *zSrc = db_column_text(&qatt, 1);
2102 const char *zTarget = db_column_text(&qatt, 2);
2103 const char *zName = db_column_text(&qatt, 3);
2104 const char isAdd = (zSrc && zSrc[0]) ? 1 : 0;
2105 char *zComment;
2106 if( isAdd ){
2107 zComment = mprintf(
2108 "Add attachment [/artifact/%!S|%h] to ticket [%!S|%S]",
2109 zSrc, zName, zTarget, zTarget);
2110 }else{
2111 zComment = mprintf("Delete attachment \"%h\" from ticket [%!S|%S]",
2112 zName, zTarget, zTarget);
2113 }
2114 db_multi_exec("UPDATE event SET comment=%Q, type='t'"
2115 " WHERE objid=%Q",
2116 zComment, zAttachId);
2117 fossil_free(zComment);
2118 }
2119 db_finalize(&qatt);
2120 }
2121 if( p->type==CFTYPE_ATTACHMENT ){
2122 char *zComment = 0;
2123 const char isAdd = (p->zAttachSrc && p->zAttachSrc[0]) ? 1 : 0;
2124 /* We assume that we're attaching to a wiki page until we
2125 ** prove otherwise (which could on a later artifact if we
2126 ** process the attachment artifact before the artifact to
2127 ** which it is attached!) */
2128 char attachToType = 'w';
2129 if( fossil_is_uuid(p->zAttachTarget) ){
2130 if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
2131 p->zAttachTarget)
2132 ){
2133 attachToType = 't'; /* Attaching to known ticket */
2134 }else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",
2135 p->zAttachTarget)
2136 ){
2137 attachToType = 'e'; /* Attaching to known tech note */
2138 }
2139 }
2140 db_multi_exec(
2141 "INSERT INTO attachment(attachid, mtime, src, target,"
2142 "filename, comment, user)"
2143 "VALUES(%d,%.17g,%Q,%Q,%Q,%Q,%Q);",
2144 rid, p->rDate, p->zAttachSrc, p->zAttachTarget, p->zAttachName,
@@ -2037,10 +2159,19 @@
2159 p->zAttachSrc, p->zAttachName, p->zAttachTarget);
2160 }else{
2161 zComment = mprintf("Delete attachment \"%h\" from wiki page [%h]",
2162 p->zAttachName, p->zAttachTarget);
2163 }
2164 }else if( 'e' == attachToType ){
2165 if( isAdd ){
2166 zComment = mprintf(
2167 "Add attachment [/artifact/%!S|%h] to tech note [/technote/%h|%.10h]",
2168 p->zAttachSrc, p->zAttachName, p->zAttachTarget, p->zAttachTarget);
2169 }else{
2170 zComment = mprintf("Delete attachment \"%h\" from tech note [%.10h]",
2171 p->zAttachName, p->zAttachTarget);
2172 }
2173 }else{
2174 if( isAdd ){
2175 zComment = mprintf(
2176 "Add attachment [/artifact/%!S|%h] to ticket [%!S|%S]",
2177 p->zAttachSrc, p->zAttachName, p->zAttachTarget, p->zAttachTarget);
@@ -2110,11 +2241,13 @@
2241 continue;
2242 }else if( strcmp(zName, "+date")==0 ){
2243 blob_appendf(&comment, " Timestamp %h.", zValue);
2244 continue;
2245 }else if( memcmp(zName, "-sym-",5)==0 ){
2246 if( !branchMove ){
2247 blob_appendf(&comment, " Cancel tag \"%h\"", &zName[5]);
2248 }
2249 }else if( memcmp(zName, "*sym-",5)==0 ){
2250 if( !branchMove ){
2251 blob_appendf(&comment, " Add propagating tag \"%h\"", &zName[5]);
2252 }
2253 }else if( memcmp(zName, "+sym-",5)==0 ){
2254
--- src/setup.c
+++ src/setup.c
@@ -1375,10 +1375,16 @@
13751375
"timeline-plaintext", "tpt", 0, 0);
13761376
@ <p>In timeline displays, check-in comments are displayed literally,
13771377
@ without any wiki or HTML interpretation. (Note: Use CSS to change
13781378
@ display formatting features such as fonts and line-wrapping behavior.)</p>
13791379
1380
+ @ <hr />
1381
+ onoff_attribute("Truncate comment at first blank line",
1382
+ "timeline-truncate-at-blank", "ttb", 0, 0);
1383
+ @ <p>In timeline displays, check-in comments are displayed only through
1384
+ @ the first blank line.</p>
1385
+
13801386
@ <hr />
13811387
onoff_attribute("Use Universal Coordinated Time (UTC)",
13821388
"timeline-utc", "utc", 1, 0);
13831389
@ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or
13841390
@ Zulu) instead of in local time. On this server, local time is currently
13851391
--- src/setup.c
+++ src/setup.c
@@ -1375,10 +1375,16 @@
1375 "timeline-plaintext", "tpt", 0, 0);
1376 @ <p>In timeline displays, check-in comments are displayed literally,
1377 @ without any wiki or HTML interpretation. (Note: Use CSS to change
1378 @ display formatting features such as fonts and line-wrapping behavior.)</p>
1379
 
 
 
 
 
 
1380 @ <hr />
1381 onoff_attribute("Use Universal Coordinated Time (UTC)",
1382 "timeline-utc", "utc", 1, 0);
1383 @ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or
1384 @ Zulu) instead of in local time. On this server, local time is currently
1385
--- src/setup.c
+++ src/setup.c
@@ -1375,10 +1375,16 @@
1375 "timeline-plaintext", "tpt", 0, 0);
1376 @ <p>In timeline displays, check-in comments are displayed literally,
1377 @ without any wiki or HTML interpretation. (Note: Use CSS to change
1378 @ display formatting features such as fonts and line-wrapping behavior.)</p>
1379
1380 @ <hr />
1381 onoff_attribute("Truncate comment at first blank line",
1382 "timeline-truncate-at-blank", "ttb", 0, 0);
1383 @ <p>In timeline displays, check-in comments are displayed only through
1384 @ the first blank line.</p>
1385
1386 @ <hr />
1387 onoff_attribute("Use Universal Coordinated Time (UTC)",
1388 "timeline-utc", "utc", 1, 0);
1389 @ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or
1390 @ Zulu) instead of in local time. On this server, local time is currently
1391
+389 -311
--- src/shell.c
+++ src/shell.c
@@ -327,10 +327,17 @@
327327
** Threat stdin as an interactive input if the following variable
328328
** is true. Otherwise, assume stdin is connected to a file or pipe.
329329
*/
330330
static int stdin_is_interactive = 1;
331331
332
+/*
333
+** On Windows systems we have to know if standard output is a console
334
+** in order to translate UTF-8 into MBCS. The following variable is
335
+** true if translation is required.
336
+*/
337
+static int stdout_is_console = 1;
338
+
332339
/*
333340
** The following is the open SQLite database. We make a pointer
334341
** to this database a static variable so that it can be accessed
335342
** by the SIGINT handler to interrupt database processing.
336343
*/
@@ -427,10 +434,20 @@
427434
UNUSED_PARAMETER(argc);
428435
UNUSED_PARAMETER(argv);
429436
sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC);
430437
}
431438
439
+
440
+/*
441
+** Compute a string length that is limited to what can be stored in
442
+** lower 30 bits of a 32-bit signed integer.
443
+*/
444
+static int strlen30(const char *z){
445
+ const char *z2 = z;
446
+ while( *z2 ){ z2++; }
447
+ return 0x3fffffff & (int)(z2 - z);
448
+}
432449
433450
/*
434451
** This routine reads a line of text from FILE in, stores
435452
** the text in memory obtained from malloc() and returns a pointer
436453
** to the text. NULL is returned at end of file, or if malloc()
@@ -463,10 +480,30 @@
463480
if( n>0 && zLine[n-1]=='\r' ) n--;
464481
zLine[n] = 0;
465482
break;
466483
}
467484
}
485
+#if defined(_WIN32) || defined(WIN32)
486
+ /* For interactive input on Windows systems, translate the
487
+ ** multi-byte characterset characters into UTF-8. */
488
+ if( stdin_is_interactive ){
489
+ extern char *sqlite3_win32_mbcs_to_utf8(const char*);
490
+ char *zTrans = sqlite3_win32_mbcs_to_utf8(zLine);
491
+ if( zTrans ){
492
+ int nTrans = strlen30(zTrans)+1;
493
+ if( nTrans>nLine ){
494
+ zLine = realloc(zLine, nTrans);
495
+ if( zLine==0 ){
496
+ sqlite3_free(zTrans);
497
+ return 0;
498
+ }
499
+ }
500
+ memcpy(zLine, zTrans, nTrans);
501
+ sqlite3_free(zTrans);
502
+ }
503
+ }
504
+#endif /* defined(_WIN32) || defined(WIN32) */
468505
return zLine;
469506
}
470507
471508
/*
472509
** Retrieve a single line of input text.
@@ -500,10 +537,43 @@
500537
#endif
501538
}
502539
return zResult;
503540
}
504541
542
+/*
543
+** Render output like fprintf(). Except, if the output is going to the
544
+** console and if this is running on a Windows machine, translate the
545
+** output from UTF-8 into MBCS.
546
+*/
547
+#if defined(_WIN32) || defined(WIN32)
548
+void utf8_printf(FILE *out, const char *zFormat, ...){
549
+ va_list ap;
550
+ va_start(ap, zFormat);
551
+ if( stdout_is_console && (out==stdout || out==stderr) ){
552
+ extern char *sqlite3_win32_utf8_to_mbcs(const char*);
553
+ char *z1 = sqlite3_vmprintf(zFormat, ap);
554
+ char *z2 = sqlite3_win32_utf8_to_mbcs(z1);
555
+ sqlite3_free(z1);
556
+ fputs(z2, out);
557
+ sqlite3_free(z2);
558
+ }else{
559
+ vfprintf(out, zFormat, ap);
560
+ }
561
+ va_end(ap);
562
+}
563
+#elif !defined(utf8_printf)
564
+# define utf8_printf fprintf
565
+#endif
566
+
567
+/*
568
+** Render output like fprintf(). This should not be used on anything that
569
+** includes string formatting (e.g. "%s").
570
+*/
571
+#if !defined(raw_printf)
572
+# define raw_printf fprintf
573
+#endif
574
+
505575
/*
506576
** Shell output mode information from before ".explain on",
507577
** saved so that it can be restored by ".explain off"
508578
*/
509579
typedef struct SavedModeInfo SavedModeInfo;
@@ -605,39 +675,29 @@
605675
/*
606676
** Number of elements in an array
607677
*/
608678
#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
609679
610
-/*
611
-** Compute a string length that is limited to what can be stored in
612
-** lower 30 bits of a 32-bit signed integer.
613
-*/
614
-static int strlen30(const char *z){
615
- const char *z2 = z;
616
- while( *z2 ){ z2++; }
617
- return 0x3fffffff & (int)(z2 - z);
618
-}
619
-
620680
/*
621681
** A callback for the sqlite3_log() interface.
622682
*/
623683
static void shellLog(void *pArg, int iErrCode, const char *zMsg){
624684
ShellState *p = (ShellState*)pArg;
625685
if( p->pLog==0 ) return;
626
- fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
686
+ utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
627687
fflush(p->pLog);
628688
}
629689
630690
/*
631691
** Output the given string as a hex-encoded blob (eg. X'1234' )
632692
*/
633693
static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
634694
int i;
635695
char *zBlob = (char *)pBlob;
636
- fprintf(out,"X'");
637
- for(i=0; i<nBlob; i++){ fprintf(out,"%02x",zBlob[i]&0xff); }
638
- fprintf(out,"'");
696
+ raw_printf(out,"X'");
697
+ for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
698
+ raw_printf(out,"'");
639699
}
640700
641701
/*
642702
** Output the given string as a quoted string using SQL quoting conventions.
643703
*/
@@ -647,27 +707,27 @@
647707
setBinaryMode(out);
648708
for(i=0; z[i]; i++){
649709
if( z[i]=='\'' ) nSingle++;
650710
}
651711
if( nSingle==0 ){
652
- fprintf(out,"'%s'",z);
712
+ utf8_printf(out,"'%s'",z);
653713
}else{
654
- fprintf(out,"'");
714
+ raw_printf(out,"'");
655715
while( *z ){
656716
for(i=0; z[i] && z[i]!='\''; i++){}
657717
if( i==0 ){
658
- fprintf(out,"''");
718
+ raw_printf(out,"''");
659719
z++;
660720
}else if( z[i]=='\'' ){
661
- fprintf(out,"%.*s''",i,z);
721
+ utf8_printf(out,"%.*s''",i,z);
662722
z += i+1;
663723
}else{
664
- fprintf(out,"%s",z);
724
+ utf8_printf(out,"%s",z);
665725
break;
666726
}
667727
}
668
- fprintf(out,"'");
728
+ raw_printf(out,"'");
669729
}
670730
setTextMode(out);
671731
}
672732
673733
/*
@@ -691,11 +751,11 @@
691751
fputc('n', out);
692752
}else if( c=='\r' ){
693753
fputc('\\', out);
694754
fputc('r', out);
695755
}else if( !isprint(c&0xff) ){
696
- fprintf(out, "\\%03o", c&0xff);
756
+ raw_printf(out, "\\%03o", c&0xff);
697757
}else{
698758
fputc(c, out);
699759
}
700760
}
701761
fputc('"', out);
@@ -715,22 +775,22 @@
715775
&& z[i]!='>'
716776
&& z[i]!='\"'
717777
&& z[i]!='\'';
718778
i++){}
719779
if( i>0 ){
720
- fprintf(out,"%.*s",i,z);
780
+ utf8_printf(out,"%.*s",i,z);
721781
}
722782
if( z[i]=='<' ){
723
- fprintf(out,"&lt;");
783
+ raw_printf(out,"&lt;");
724784
}else if( z[i]=='&' ){
725
- fprintf(out,"&amp;");
785
+ raw_printf(out,"&amp;");
726786
}else if( z[i]=='>' ){
727
- fprintf(out,"&gt;");
787
+ raw_printf(out,"&gt;");
728788
}else if( z[i]=='\"' ){
729
- fprintf(out,"&quot;");
789
+ raw_printf(out,"&quot;");
730790
}else if( z[i]=='\'' ){
731
- fprintf(out,"&#39;");
791
+ raw_printf(out,"&#39;");
732792
}else{
733793
break;
734794
}
735795
z += i + 1;
736796
}
@@ -766,11 +826,11 @@
766826
** is only issued if bSep is true.
767827
*/
768828
static void output_csv(ShellState *p, const char *z, int bSep){
769829
FILE *out = p->out;
770830
if( z==0 ){
771
- fprintf(out,"%s",p->nullValue);
831
+ utf8_printf(out,"%s",p->nullValue);
772832
}else{
773833
int i;
774834
int nSep = strlen30(p->colSeparator);
775835
for(i=0; z[i]; i++){
776836
if( needCsvQuote[((unsigned char*)z)[i]]
@@ -786,15 +846,15 @@
786846
if( z[i]=='"' ) putc('"', out);
787847
putc(z[i], out);
788848
}
789849
putc('"', out);
790850
}else{
791
- fprintf(out, "%s", z);
851
+ utf8_printf(out, "%s", z);
792852
}
793853
}
794854
if( bSep ){
795
- fprintf(p->out, "%s", p->colSeparator);
855
+ utf8_printf(p->out, "%s", p->colSeparator);
796856
}
797857
}
798858
799859
#ifdef SIGINT
800860
/*
@@ -828,13 +888,13 @@
828888
if( azArg==0 ) break;
829889
for(i=0; i<nArg; i++){
830890
int len = strlen30(azCol[i] ? azCol[i] : "");
831891
if( len>w ) w = len;
832892
}
833
- if( p->cnt++>0 ) fprintf(p->out, "%s", p->rowSeparator);
893
+ if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
834894
for(i=0; i<nArg; i++){
835
- fprintf(p->out,"%*s = %s%s", w, azCol[i],
895
+ utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
836896
azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
837897
}
838898
break;
839899
}
840900
case MODE_Explain:
@@ -856,14 +916,14 @@
856916
if( i<ArraySize(p->actualWidth) ){
857917
p->actualWidth[i] = w;
858918
}
859919
if( p->showHeader ){
860920
if( w<0 ){
861
- fprintf(p->out,"%*.*s%s",-w,-w,azCol[i],
921
+ utf8_printf(p->out,"%*.*s%s",-w,-w,azCol[i],
862922
i==nArg-1 ? p->rowSeparator : " ");
863923
}else{
864
- fprintf(p->out,"%-*.*s%s",w,w,azCol[i],
924
+ utf8_printf(p->out,"%-*.*s%s",w,w,azCol[i],
865925
i==nArg-1 ? p->rowSeparator : " ");
866926
}
867927
}
868928
}
869929
if( p->showHeader ){
@@ -873,11 +933,12 @@
873933
w = p->actualWidth[i];
874934
if( w<0 ) w = -w;
875935
}else{
876936
w = 10;
877937
}
878
- fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------"
938
+ utf8_printf(p->out,"%-*.*s%s",w,w,
939
+ "----------------------------------------------------------"
879940
"----------------------------------------------------------",
880941
i==nArg-1 ? p->rowSeparator : " ");
881942
}
882943
}
883944
}
@@ -892,20 +953,20 @@
892953
if( p->mode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){
893954
w = strlen30(azArg[i]);
894955
}
895956
if( i==1 && p->aiIndent && p->pStmt ){
896957
if( p->iIndent<p->nIndent ){
897
- fprintf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
958
+ utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
898959
}
899960
p->iIndent++;
900961
}
901962
if( w<0 ){
902
- fprintf(p->out,"%*.*s%s",-w,-w,
963
+ utf8_printf(p->out,"%*.*s%s",-w,-w,
903964
azArg[i] ? azArg[i] : p->nullValue,
904965
i==nArg-1 ? p->rowSeparator : " ");
905966
}else{
906
- fprintf(p->out,"%-*.*s%s",w,w,
967
+ utf8_printf(p->out,"%-*.*s%s",w,w,
907968
azArg[i] ? azArg[i] : p->nullValue,
908969
i==nArg-1 ? p->rowSeparator : " ");
909970
}
910971
}
911972
break;
@@ -912,134 +973,134 @@
912973
}
913974
case MODE_Semi:
914975
case MODE_List: {
915976
if( p->cnt++==0 && p->showHeader ){
916977
for(i=0; i<nArg; i++){
917
- fprintf(p->out,"%s%s",azCol[i],
978
+ utf8_printf(p->out,"%s%s",azCol[i],
918979
i==nArg-1 ? p->rowSeparator : p->colSeparator);
919980
}
920981
}
921982
if( azArg==0 ) break;
922983
for(i=0; i<nArg; i++){
923984
char *z = azArg[i];
924985
if( z==0 ) z = p->nullValue;
925
- fprintf(p->out, "%s", z);
986
+ utf8_printf(p->out, "%s", z);
926987
if( i<nArg-1 ){
927
- fprintf(p->out, "%s", p->colSeparator);
988
+ utf8_printf(p->out, "%s", p->colSeparator);
928989
}else if( p->mode==MODE_Semi ){
929
- fprintf(p->out, ";%s", p->rowSeparator);
990
+ utf8_printf(p->out, ";%s", p->rowSeparator);
930991
}else{
931
- fprintf(p->out, "%s", p->rowSeparator);
992
+ utf8_printf(p->out, "%s", p->rowSeparator);
932993
}
933994
}
934995
break;
935996
}
936997
case MODE_Html: {
937998
if( p->cnt++==0 && p->showHeader ){
938
- fprintf(p->out,"<TR>");
999
+ raw_printf(p->out,"<TR>");
9391000
for(i=0; i<nArg; i++){
940
- fprintf(p->out,"<TH>");
1001
+ raw_printf(p->out,"<TH>");
9411002
output_html_string(p->out, azCol[i]);
942
- fprintf(p->out,"</TH>\n");
1003
+ raw_printf(p->out,"</TH>\n");
9431004
}
944
- fprintf(p->out,"</TR>\n");
1005
+ raw_printf(p->out,"</TR>\n");
9451006
}
9461007
if( azArg==0 ) break;
947
- fprintf(p->out,"<TR>");
1008
+ raw_printf(p->out,"<TR>");
9481009
for(i=0; i<nArg; i++){
949
- fprintf(p->out,"<TD>");
1010
+ raw_printf(p->out,"<TD>");
9501011
output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
951
- fprintf(p->out,"</TD>\n");
1012
+ raw_printf(p->out,"</TD>\n");
9521013
}
953
- fprintf(p->out,"</TR>\n");
1014
+ raw_printf(p->out,"</TR>\n");
9541015
break;
9551016
}
9561017
case MODE_Tcl: {
9571018
if( p->cnt++==0 && p->showHeader ){
9581019
for(i=0; i<nArg; i++){
9591020
output_c_string(p->out,azCol[i] ? azCol[i] : "");
960
- if(i<nArg-1) fprintf(p->out, "%s", p->colSeparator);
1021
+ if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
9611022
}
962
- fprintf(p->out, "%s", p->rowSeparator);
1023
+ utf8_printf(p->out, "%s", p->rowSeparator);
9631024
}
9641025
if( azArg==0 ) break;
9651026
for(i=0; i<nArg; i++){
9661027
output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
967
- if(i<nArg-1) fprintf(p->out, "%s", p->colSeparator);
1028
+ if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
9681029
}
969
- fprintf(p->out, "%s", p->rowSeparator);
1030
+ utf8_printf(p->out, "%s", p->rowSeparator);
9701031
break;
9711032
}
9721033
case MODE_Csv: {
9731034
setBinaryMode(p->out);
9741035
if( p->cnt++==0 && p->showHeader ){
9751036
for(i=0; i<nArg; i++){
9761037
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
9771038
}
978
- fprintf(p->out, "%s", p->rowSeparator);
1039
+ utf8_printf(p->out, "%s", p->rowSeparator);
9791040
}
9801041
if( nArg>0 ){
9811042
for(i=0; i<nArg; i++){
9821043
output_csv(p, azArg[i], i<nArg-1);
9831044
}
984
- fprintf(p->out, "%s", p->rowSeparator);
1045
+ utf8_printf(p->out, "%s", p->rowSeparator);
9851046
}
9861047
setTextMode(p->out);
9871048
break;
9881049
}
9891050
case MODE_Insert: {
9901051
p->cnt++;
9911052
if( azArg==0 ) break;
992
- fprintf(p->out,"INSERT INTO %s",p->zDestTable);
1053
+ utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
9931054
if( p->showHeader ){
994
- fprintf(p->out,"(");
1055
+ raw_printf(p->out,"(");
9951056
for(i=0; i<nArg; i++){
9961057
char *zSep = i>0 ? ",": "";
997
- fprintf(p->out, "%s%s", zSep, azCol[i]);
1058
+ utf8_printf(p->out, "%s%s", zSep, azCol[i]);
9981059
}
999
- fprintf(p->out,")");
1060
+ raw_printf(p->out,")");
10001061
}
1001
- fprintf(p->out," VALUES(");
1062
+ raw_printf(p->out," VALUES(");
10021063
for(i=0; i<nArg; i++){
10031064
char *zSep = i>0 ? ",": "";
10041065
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
1005
- fprintf(p->out,"%sNULL",zSep);
1066
+ utf8_printf(p->out,"%sNULL",zSep);
10061067
}else if( aiType && aiType[i]==SQLITE_TEXT ){
1007
- if( zSep[0] ) fprintf(p->out,"%s",zSep);
1068
+ if( zSep[0] ) utf8_printf(p->out,"%s",zSep);
10081069
output_quoted_string(p->out, azArg[i]);
10091070
}else if( aiType && (aiType[i]==SQLITE_INTEGER
10101071
|| aiType[i]==SQLITE_FLOAT) ){
1011
- fprintf(p->out,"%s%s",zSep, azArg[i]);
1072
+ utf8_printf(p->out,"%s%s",zSep, azArg[i]);
10121073
}else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
10131074
const void *pBlob = sqlite3_column_blob(p->pStmt, i);
10141075
int nBlob = sqlite3_column_bytes(p->pStmt, i);
1015
- if( zSep[0] ) fprintf(p->out,"%s",zSep);
1076
+ if( zSep[0] ) utf8_printf(p->out,"%s",zSep);
10161077
output_hex_blob(p->out, pBlob, nBlob);
10171078
}else if( isNumber(azArg[i], 0) ){
1018
- fprintf(p->out,"%s%s",zSep, azArg[i]);
1079
+ utf8_printf(p->out,"%s%s",zSep, azArg[i]);
10191080
}else{
1020
- if( zSep[0] ) fprintf(p->out,"%s",zSep);
1081
+ if( zSep[0] ) utf8_printf(p->out,"%s",zSep);
10211082
output_quoted_string(p->out, azArg[i]);
10221083
}
10231084
}
1024
- fprintf(p->out,");\n");
1085
+ raw_printf(p->out,");\n");
10251086
break;
10261087
}
10271088
case MODE_Ascii: {
10281089
if( p->cnt++==0 && p->showHeader ){
10291090
for(i=0; i<nArg; i++){
1030
- if( i>0 ) fprintf(p->out, "%s", p->colSeparator);
1031
- fprintf(p->out,"%s",azCol[i] ? azCol[i] : "");
1091
+ if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
1092
+ utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
10321093
}
1033
- fprintf(p->out, "%s", p->rowSeparator);
1094
+ utf8_printf(p->out, "%s", p->rowSeparator);
10341095
}
10351096
if( azArg==0 ) break;
10361097
for(i=0; i<nArg; i++){
1037
- if( i>0 ) fprintf(p->out, "%s", p->colSeparator);
1038
- fprintf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
1098
+ if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
1099
+ utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
10391100
}
1040
- fprintf(p->out, "%s", p->rowSeparator);
1101
+ utf8_printf(p->out, "%s", p->rowSeparator);
10411102
break;
10421103
}
10431104
}
10441105
return 0;
10451106
}
@@ -1076,11 +1137,11 @@
10761137
}
10771138
}
10781139
if( needQuote ) n += 2;
10791140
z = p->zDestTable = malloc( n+1 );
10801141
if( z==0 ){
1081
- fprintf(stderr,"Error: out of memory\n");
1142
+ raw_printf(stderr,"Error: out of memory\n");
10821143
exit(1);
10831144
}
10841145
n = 0;
10851146
if( needQuote ) z[n++] = '\'';
10861147
for(i=0; zName[i]; i++){
@@ -1157,38 +1218,40 @@
11571218
int nResult;
11581219
int i;
11591220
const char *z;
11601221
rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
11611222
if( rc!=SQLITE_OK || !pSelect ){
1162
- fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
1223
+ utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
1224
+ sqlite3_errmsg(p->db));
11631225
if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
11641226
return rc;
11651227
}
11661228
rc = sqlite3_step(pSelect);
11671229
nResult = sqlite3_column_count(pSelect);
11681230
while( rc==SQLITE_ROW ){
11691231
if( zFirstRow ){
1170
- fprintf(p->out, "%s", zFirstRow);
1232
+ utf8_printf(p->out, "%s", zFirstRow);
11711233
zFirstRow = 0;
11721234
}
11731235
z = (const char*)sqlite3_column_text(pSelect, 0);
1174
- fprintf(p->out, "%s", z);
1236
+ utf8_printf(p->out, "%s", z);
11751237
for(i=1; i<nResult; i++){
1176
- fprintf(p->out, ",%s", sqlite3_column_text(pSelect, i));
1238
+ utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
11771239
}
11781240
if( z==0 ) z = "";
11791241
while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
11801242
if( z[0] ){
1181
- fprintf(p->out, "\n;\n");
1243
+ raw_printf(p->out, "\n;\n");
11821244
}else{
1183
- fprintf(p->out, ";\n");
1245
+ raw_printf(p->out, ";\n");
11841246
}
11851247
rc = sqlite3_step(pSelect);
11861248
}
11871249
rc = sqlite3_finalize(pSelect);
11881250
if( rc!=SQLITE_OK ){
1189
- fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
1251
+ utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
1252
+ sqlite3_errmsg(p->db));
11901253
if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
11911254
}
11921255
return rc;
11931256
}
11941257
@@ -1219,107 +1282,115 @@
12191282
12201283
if( pArg && pArg->out ){
12211284
12221285
iHiwtr = iCur = -1;
12231286
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset);
1224
- fprintf(pArg->out,
1287
+ raw_printf(pArg->out,
12251288
"Memory Used: %d (max %d) bytes\n",
12261289
iCur, iHiwtr);
12271290
iHiwtr = iCur = -1;
12281291
sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset);
1229
- fprintf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n",
1292
+ raw_printf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n",
12301293
iCur, iHiwtr);
12311294
if( pArg->shellFlgs & SHFLG_Pagecache ){
12321295
iHiwtr = iCur = -1;
12331296
sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset);
1234
- fprintf(pArg->out,
1297
+ raw_printf(pArg->out,
12351298
"Number of Pcache Pages Used: %d (max %d) pages\n",
12361299
iCur, iHiwtr);
12371300
}
12381301
iHiwtr = iCur = -1;
12391302
sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset);
1240
- fprintf(pArg->out,
1303
+ raw_printf(pArg->out,
12411304
"Number of Pcache Overflow Bytes: %d (max %d) bytes\n",
12421305
iCur, iHiwtr);
12431306
if( pArg->shellFlgs & SHFLG_Scratch ){
12441307
iHiwtr = iCur = -1;
12451308
sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset);
1246
- fprintf(pArg->out, "Number of Scratch Allocations Used: %d (max %d)\n",
1309
+ raw_printf(pArg->out,
1310
+ "Number of Scratch Allocations Used: %d (max %d)\n",
12471311
iCur, iHiwtr);
12481312
}
12491313
iHiwtr = iCur = -1;
12501314
sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset);
1251
- fprintf(pArg->out,
1315
+ raw_printf(pArg->out,
12521316
"Number of Scratch Overflow Bytes: %d (max %d) bytes\n",
12531317
iCur, iHiwtr);
12541318
iHiwtr = iCur = -1;
12551319
sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset);
1256
- fprintf(pArg->out, "Largest Allocation: %d bytes\n",
1320
+ raw_printf(pArg->out, "Largest Allocation: %d bytes\n",
12571321
iHiwtr);
12581322
iHiwtr = iCur = -1;
12591323
sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset);
1260
- fprintf(pArg->out, "Largest Pcache Allocation: %d bytes\n",
1324
+ raw_printf(pArg->out, "Largest Pcache Allocation: %d bytes\n",
12611325
iHiwtr);
12621326
iHiwtr = iCur = -1;
12631327
sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset);
1264
- fprintf(pArg->out, "Largest Scratch Allocation: %d bytes\n",
1328
+ raw_printf(pArg->out, "Largest Scratch Allocation: %d bytes\n",
12651329
iHiwtr);
12661330
#ifdef YYTRACKMAXSTACKDEPTH
12671331
iHiwtr = iCur = -1;
12681332
sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset);
1269
- fprintf(pArg->out, "Deepest Parser Stack: %d (max %d)\n",
1333
+ raw_printf(pArg->out, "Deepest Parser Stack: %d (max %d)\n",
12701334
iCur, iHiwtr);
12711335
#endif
12721336
}
12731337
12741338
if( pArg && pArg->out && db ){
12751339
if( pArg->shellFlgs & SHFLG_Lookaside ){
12761340
iHiwtr = iCur = -1;
12771341
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
12781342
&iCur, &iHiwtr, bReset);
1279
- fprintf(pArg->out, "Lookaside Slots Used: %d (max %d)\n",
1343
+ raw_printf(pArg->out,
1344
+ "Lookaside Slots Used: %d (max %d)\n",
12801345
iCur, iHiwtr);
12811346
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
12821347
&iCur, &iHiwtr, bReset);
1283
- fprintf(pArg->out, "Successful lookaside attempts: %d\n", iHiwtr);
1348
+ raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
1349
+ iHiwtr);
12841350
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
12851351
&iCur, &iHiwtr, bReset);
1286
- fprintf(pArg->out, "Lookaside failures due to size: %d\n", iHiwtr);
1352
+ raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
1353
+ iHiwtr);
12871354
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
12881355
&iCur, &iHiwtr, bReset);
1289
- fprintf(pArg->out, "Lookaside failures due to OOM: %d\n", iHiwtr);
1356
+ raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
1357
+ iHiwtr);
12901358
}
12911359
iHiwtr = iCur = -1;
12921360
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
1293
- fprintf(pArg->out, "Pager Heap Usage: %d bytes\n",iCur);
1361
+ raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
1362
+ iCur);
12941363
iHiwtr = iCur = -1;
12951364
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
1296
- fprintf(pArg->out, "Page cache hits: %d\n", iCur);
1365
+ raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
12971366
iHiwtr = iCur = -1;
12981367
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
1299
- fprintf(pArg->out, "Page cache misses: %d\n", iCur);
1368
+ raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
13001369
iHiwtr = iCur = -1;
13011370
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
1302
- fprintf(pArg->out, "Page cache writes: %d\n", iCur);
1371
+ raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
13031372
iHiwtr = iCur = -1;
13041373
sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
1305
- fprintf(pArg->out, "Schema Heap Usage: %d bytes\n",iCur);
1374
+ raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
1375
+ iCur);
13061376
iHiwtr = iCur = -1;
13071377
sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
1308
- fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",iCur);
1378
+ raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
1379
+ iCur);
13091380
}
13101381
13111382
if( pArg && pArg->out && db && pArg->pStmt ){
13121383
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
13131384
bReset);
1314
- fprintf(pArg->out, "Fullscan Steps: %d\n", iCur);
1385
+ raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
13151386
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
1316
- fprintf(pArg->out, "Sort Operations: %d\n", iCur);
1387
+ raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
13171388
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
1318
- fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur);
1389
+ raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
13191390
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
1320
- fprintf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
1391
+ raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
13211392
}
13221393
13231394
/* Do not remove this machine readable comment: extra-stats-output-here */
13241395
13251396
return 0;
@@ -1335,11 +1406,11 @@
13351406
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
13361407
UNUSED_PARAMETER(db);
13371408
UNUSED_PARAMETER(pArg);
13381409
#else
13391410
int i, k, n, mx;
1340
- fprintf(pArg->out, "-------- scanstats --------\n");
1411
+ raw_printf(pArg->out, "-------- scanstats --------\n");
13411412
mx = 0;
13421413
for(k=0; k<=mx; k++){
13431414
double rEstLoop = 1.0;
13441415
for(i=n=0; 1; i++){
13451416
sqlite3_stmt *p = pArg->pStmt;
@@ -1353,25 +1424,25 @@
13531424
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
13541425
if( iSid>mx ) mx = iSid;
13551426
if( iSid!=k ) continue;
13561427
if( n==0 ){
13571428
rEstLoop = (double)nLoop;
1358
- if( k>0 ) fprintf(pArg->out, "-------- subquery %d -------\n", k);
1429
+ if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
13591430
}
13601431
n++;
13611432
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
13621433
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
13631434
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
1364
- fprintf(pArg->out, "Loop %2d: %s\n", n, zExplain);
1435
+ utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
13651436
rEstLoop *= rEst;
1366
- fprintf(pArg->out,
1437
+ raw_printf(pArg->out,
13671438
" nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
13681439
nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
13691440
);
13701441
}
13711442
}
1372
- fprintf(pArg->out, "---------------------------\n");
1443
+ raw_printf(pArg->out, "---------------------------\n");
13731444
#endif
13741445
}
13751446
13761447
/*
13771448
** Parameter azArray points to a zero-terminated array of strings. zStr
@@ -1520,11 +1591,11 @@
15201591
}
15211592
15221593
/* echo the sql statement if echo on */
15231594
if( pArg && pArg->echoOn ){
15241595
const char *zStmtSql = sqlite3_sql(pStmt);
1525
- fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
1596
+ utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
15261597
}
15271598
15281599
/* Show the EXPLAIN QUERY PLAN if .eqp is on */
15291600
if( pArg && pArg->autoEQP ){
15301601
sqlite3_stmt *pExplain;
@@ -1531,14 +1602,14 @@
15311602
char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s",
15321603
sqlite3_sql(pStmt));
15331604
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
15341605
if( rc==SQLITE_OK ){
15351606
while( sqlite3_step(pExplain)==SQLITE_ROW ){
1536
- fprintf(pArg->out,"--EQP-- %d,", sqlite3_column_int(pExplain, 0));
1537
- fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1));
1538
- fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2));
1539
- fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
1607
+ raw_printf(pArg->out,"--EQP-- %d,",sqlite3_column_int(pExplain, 0));
1608
+ raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1));
1609
+ raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2));
1610
+ utf8_printf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
15401611
}
15411612
}
15421613
sqlite3_finalize(pExplain);
15431614
sqlite3_free(zEQP);
15441615
}
@@ -1662,28 +1733,28 @@
16621733
zSql = azArg[2];
16631734
16641735
if( strcmp(zTable, "sqlite_sequence")==0 ){
16651736
zPrepStmt = "DELETE FROM sqlite_sequence;\n";
16661737
}else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
1667
- fprintf(p->out, "ANALYZE sqlite_master;\n");
1738
+ raw_printf(p->out, "ANALYZE sqlite_master;\n");
16681739
}else if( strncmp(zTable, "sqlite_", 7)==0 ){
16691740
return 0;
16701741
}else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
16711742
char *zIns;
16721743
if( !p->writableSchema ){
1673
- fprintf(p->out, "PRAGMA writable_schema=ON;\n");
1744
+ raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
16741745
p->writableSchema = 1;
16751746
}
16761747
zIns = sqlite3_mprintf(
16771748
"INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
16781749
"VALUES('table','%q','%q',0,'%q');",
16791750
zTable, zTable, zSql);
1680
- fprintf(p->out, "%s\n", zIns);
1751
+ utf8_printf(p->out, "%s\n", zIns);
16811752
sqlite3_free(zIns);
16821753
return 0;
16831754
}else{
1684
- fprintf(p->out, "%s;\n", zSql);
1755
+ utf8_printf(p->out, "%s;\n", zSql);
16851756
}
16861757
16871758
if( strcmp(zType, "table")==0 ){
16881759
sqlite3_stmt *pTableInfo = 0;
16891760
char *zSelect = 0;
@@ -1756,22 +1827,22 @@
17561827
char *zErr = 0;
17571828
rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
17581829
if( rc==SQLITE_CORRUPT ){
17591830
char *zQ2;
17601831
int len = strlen30(zQuery);
1761
- fprintf(p->out, "/****** CORRUPTION ERROR *******/\n");
1832
+ raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
17621833
if( zErr ){
1763
- fprintf(p->out, "/****** %s ******/\n", zErr);
1834
+ utf8_printf(p->out, "/****** %s ******/\n", zErr);
17641835
sqlite3_free(zErr);
17651836
zErr = 0;
17661837
}
17671838
zQ2 = malloc( len+100 );
17681839
if( zQ2==0 ) return rc;
17691840
sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
17701841
rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
17711842
if( rc ){
1772
- fprintf(p->out, "/****** ERROR: %s ******/\n", zErr);
1843
+ utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
17731844
}else{
17741845
rc = SQLITE_CORRUPT;
17751846
}
17761847
sqlite3_free(zErr);
17771848
free(zQ2);
@@ -1932,11 +2003,11 @@
19322003
if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){
19332004
sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0,
19342005
shellstaticFunc, 0, 0);
19352006
}
19362007
if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
1937
- fprintf(stderr,"Error: unable to open database \"%s\": %s\n",
2008
+ utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
19382009
p->zDbFilename, sqlite3_errmsg(p->db));
19392010
if( keepAlive ) return;
19402011
exit(1);
19412012
}
19422013
#ifndef SQLITE_OMIT_LOAD_EXTENSION
@@ -2082,11 +2153,11 @@
20822153
return 1;
20832154
}
20842155
if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
20852156
return 0;
20862157
}
2087
- fprintf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
2158
+ utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
20882159
zArg);
20892160
return 0;
20902161
}
20912162
20922163
/*
@@ -2110,11 +2181,11 @@
21102181
}else if( strcmp(zFile, "off")==0 ){
21112182
f = 0;
21122183
}else{
21132184
f = fopen(zFile, "wb");
21142185
if( f==0 ){
2115
- fprintf(stderr, "Error: cannot open \"%s\"\n", zFile);
2186
+ utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
21162187
}
21172188
}
21182189
return f;
21192190
}
21202191
@@ -2124,11 +2195,11 @@
21242195
static void sql_trace_callback(void *pArg, const char *z){
21252196
FILE *f = (FILE*)pArg;
21262197
if( f ){
21272198
int i = (int)strlen(z);
21282199
while( i>0 && z[i-1]==';' ){ i--; }
2129
- fprintf(f, "%.*s;\n", i, z);
2200
+ utf8_printf(f, "%.*s;\n", i, z);
21302201
}
21312202
}
21322203
21332204
/*
21342205
** A no-op routine that runs with the ".breakpoint" doc-command. This is
@@ -2159,11 +2230,11 @@
21592230
static void import_append_char(ImportCtx *p, int c){
21602231
if( p->n+1>=p->nAlloc ){
21612232
p->nAlloc += p->nAlloc + 100;
21622233
p->z = sqlite3_realloc64(p->z, p->nAlloc);
21632234
if( p->z==0 ){
2164
- fprintf(stderr, "out of memory\n");
2235
+ raw_printf(stderr, "out of memory\n");
21652236
exit(1);
21662237
}
21672238
}
21682239
p->z[p->n++] = (char)c;
21692240
}
@@ -2213,15 +2284,15 @@
22132284
do{ p->n--; }while( p->z[p->n]!=cQuote );
22142285
p->cTerm = c;
22152286
break;
22162287
}
22172288
if( pc==cQuote && c!='\r' ){
2218
- fprintf(stderr, "%s:%d: unescaped %c character\n",
2289
+ utf8_printf(stderr, "%s:%d: unescaped %c character\n",
22192290
p->zFile, p->nLine, cQuote);
22202291
}
22212292
if( c==EOF ){
2222
- fprintf(stderr, "%s:%d: unterminated %c-quoted field\n",
2293
+ utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
22232294
p->zFile, startLine, cQuote);
22242295
p->cTerm = c;
22252296
break;
22262297
}
22272298
import_append_char(p, c);
@@ -2299,19 +2370,19 @@
22992370
const int spinRate = 10000;
23002371
23012372
zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
23022373
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
23032374
if( rc ){
2304
- fprintf(stderr, "Error %d: %s on [%s]\n",
2375
+ utf8_printf(stderr, "Error %d: %s on [%s]\n",
23052376
sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
23062377
zQuery);
23072378
goto end_data_xfer;
23082379
}
23092380
n = sqlite3_column_count(pQuery);
23102381
zInsert = sqlite3_malloc64(200 + nTable + n*3);
23112382
if( zInsert==0 ){
2312
- fprintf(stderr, "out of memory\n");
2383
+ raw_printf(stderr, "out of memory\n");
23132384
goto end_data_xfer;
23142385
}
23152386
sqlite3_snprintf(200+nTable,zInsert,
23162387
"INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
23172388
i = (int)strlen(zInsert);
@@ -2320,11 +2391,11 @@
23202391
i += 2;
23212392
}
23222393
memcpy(zInsert+i, ");", 3);
23232394
rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
23242395
if( rc ){
2325
- fprintf(stderr, "Error %d: %s on [%s]\n",
2396
+ utf8_printf(stderr, "Error %d: %s on [%s]\n",
23262397
sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
23272398
zQuery);
23282399
goto end_data_xfer;
23292400
}
23302401
for(k=0; k<2; k++){
@@ -2357,11 +2428,11 @@
23572428
}
23582429
}
23592430
} /* End for */
23602431
rc = sqlite3_step(pInsert);
23612432
if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
2362
- fprintf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
2433
+ utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
23632434
sqlite3_errmsg(newDb));
23642435
}
23652436
sqlite3_reset(pInsert);
23662437
cnt++;
23672438
if( (cnt%spinRate)==0 ){
@@ -2374,11 +2445,11 @@
23742445
sqlite3_free(zQuery);
23752446
zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
23762447
zTable);
23772448
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
23782449
if( rc ){
2379
- fprintf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
2450
+ utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
23802451
break;
23812452
}
23822453
} /* End for(k=0...) */
23832454
23842455
end_data_xfer:
@@ -2410,11 +2481,11 @@
24102481
24112482
zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
24122483
" WHERE %s", zWhere);
24132484
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
24142485
if( rc ){
2415
- fprintf(stderr, "Error: (%d) %s on [%s]\n",
2486
+ utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
24162487
sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
24172488
zQuery);
24182489
goto end_schema_xfer;
24192490
}
24202491
while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
@@ -2421,11 +2492,11 @@
24212492
zName = sqlite3_column_text(pQuery, 0);
24222493
zSql = sqlite3_column_text(pQuery, 1);
24232494
printf("%s... ", zName); fflush(stdout);
24242495
sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
24252496
if( zErrMsg ){
2426
- fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
2497
+ utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
24272498
sqlite3_free(zErrMsg);
24282499
zErrMsg = 0;
24292500
}
24302501
if( xForEach ){
24312502
xForEach(p, newDb, (const char*)zName);
@@ -2437,11 +2508,11 @@
24372508
sqlite3_free(zQuery);
24382509
zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
24392510
" WHERE %s ORDER BY rowid DESC", zWhere);
24402511
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
24412512
if( rc ){
2442
- fprintf(stderr, "Error: (%d) %s on [%s]\n",
2513
+ utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
24432514
sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
24442515
zQuery);
24452516
goto end_schema_xfer;
24462517
}
24472518
while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
@@ -2448,11 +2519,11 @@
24482519
zName = sqlite3_column_text(pQuery, 0);
24492520
zSql = sqlite3_column_text(pQuery, 1);
24502521
printf("%s... ", zName); fflush(stdout);
24512522
sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
24522523
if( zErrMsg ){
2453
- fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
2524
+ utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
24542525
sqlite3_free(zErrMsg);
24552526
zErrMsg = 0;
24562527
}
24572528
if( xForEach ){
24582529
xForEach(p, newDb, (const char*)zName);
@@ -2472,16 +2543,16 @@
24722543
*/
24732544
static void tryToClone(ShellState *p, const char *zNewDb){
24742545
int rc;
24752546
sqlite3 *newDb = 0;
24762547
if( access(zNewDb,0)==0 ){
2477
- fprintf(stderr, "File \"%s\" already exists.\n", zNewDb);
2548
+ utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
24782549
return;
24792550
}
24802551
rc = sqlite3_open(zNewDb, &newDb);
24812552
if( rc ){
2482
- fprintf(stderr, "Cannot create output database: %s\n",
2553
+ utf8_printf(stderr, "Cannot create output database: %s\n",
24832554
sqlite3_errmsg(newDb));
24842555
}else{
24852556
sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
24862557
sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
24872558
tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
@@ -2574,31 +2645,31 @@
25742645
if( pFile==0 || pFile->pMethods==0 || pFile->pMethods->xRead==0 ){
25752646
return 1;
25762647
}
25772648
i = pFile->pMethods->xRead(pFile, aHdr, 100, 0);
25782649
if( i!=SQLITE_OK ){
2579
- fprintf(stderr, "unable to read database header\n");
2650
+ raw_printf(stderr, "unable to read database header\n");
25802651
return 1;
25812652
}
25822653
i = get2byteInt(aHdr+16);
25832654
if( i==1 ) i = 65536;
2584
- fprintf(p->out, "%-20s %d\n", "database page size:", i);
2585
- fprintf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
2586
- fprintf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
2587
- fprintf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
2655
+ utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
2656
+ utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
2657
+ utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
2658
+ utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
25882659
for(i=0; i<ArraySize(aField); i++){
25892660
int ofst = aField[i].ofst;
25902661
unsigned int val = get4byteInt(aHdr + ofst);
2591
- fprintf(p->out, "%-20s %u", aField[i].zName, val);
2662
+ utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
25922663
switch( ofst ){
25932664
case 56: {
2594
- if( val==1 ) fprintf(p->out, " (utf8)");
2595
- if( val==2 ) fprintf(p->out, " (utf16le)");
2596
- if( val==3 ) fprintf(p->out, " (utf16be)");
2665
+ if( val==1 ) raw_printf(p->out, " (utf8)");
2666
+ if( val==2 ) raw_printf(p->out, " (utf16le)");
2667
+ if( val==3 ) raw_printf(p->out, " (utf16be)");
25972668
}
25982669
}
2599
- fprintf(p->out, "\n");
2670
+ raw_printf(p->out, "\n");
26002671
}
26012672
if( zDb==0 ){
26022673
zSchemaTab = sqlite3_mprintf("main.sqlite_master");
26032674
}else if( strcmp(zDb,"temp")==0 ){
26042675
zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master");
@@ -2607,11 +2678,11 @@
26072678
}
26082679
for(i=0; i<ArraySize(aQuery); i++){
26092680
char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
26102681
int val = db_int(p, zSql);
26112682
sqlite3_free(zSql);
2612
- fprintf(p->out, "%-20s %d\n", aQuery[i].zName, val);
2683
+ utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
26132684
}
26142685
sqlite3_free(zSchemaTab);
26152686
return 0;
26162687
}
26172688
@@ -2618,19 +2689,19 @@
26182689
/*
26192690
** Print the current sqlite3_errmsg() value to stderr and return 1.
26202691
*/
26212692
static int shellDatabaseError(sqlite3 *db){
26222693
const char *zErr = sqlite3_errmsg(db);
2623
- fprintf(stderr, "Error: %s\n", zErr);
2694
+ utf8_printf(stderr, "Error: %s\n", zErr);
26242695
return 1;
26252696
}
26262697
26272698
/*
26282699
** Print an out-of-memory message to stderr and return 1.
26292700
*/
26302701
static int shellNomemError(void){
2631
- fprintf(stderr, "Error: out of memory\n");
2702
+ raw_printf(stderr, "Error: out of memory\n");
26322703
return 1;
26332704
}
26342705
26352706
/*
26362707
** If an input line begins with "." then invoke this routine to
@@ -2686,57 +2757,57 @@
26862757
const char *z = azArg[j];
26872758
if( z[0]=='-' ){
26882759
while( z[0]=='-' ) z++;
26892760
/* No options to process at this time */
26902761
{
2691
- fprintf(stderr, "unknown option: %s\n", azArg[j]);
2762
+ utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
26922763
return 1;
26932764
}
26942765
}else if( zDestFile==0 ){
26952766
zDestFile = azArg[j];
26962767
}else if( zDb==0 ){
26972768
zDb = zDestFile;
26982769
zDestFile = azArg[j];
26992770
}else{
2700
- fprintf(stderr, "too many arguments to .backup\n");
2771
+ raw_printf(stderr, "too many arguments to .backup\n");
27012772
return 1;
27022773
}
27032774
}
27042775
if( zDestFile==0 ){
2705
- fprintf(stderr, "missing FILENAME argument on .backup\n");
2776
+ raw_printf(stderr, "missing FILENAME argument on .backup\n");
27062777
return 1;
27072778
}
27082779
if( zDb==0 ) zDb = "main";
27092780
rc = sqlite3_open(zDestFile, &pDest);
27102781
if( rc!=SQLITE_OK ){
2711
- fprintf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
2782
+ utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
27122783
sqlite3_close(pDest);
27132784
return 1;
27142785
}
27152786
open_db(p, 0);
27162787
pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
27172788
if( pBackup==0 ){
2718
- fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
2789
+ utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
27192790
sqlite3_close(pDest);
27202791
return 1;
27212792
}
27222793
while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
27232794
sqlite3_backup_finish(pBackup);
27242795
if( rc==SQLITE_DONE ){
27252796
rc = 0;
27262797
}else{
2727
- fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
2798
+ utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
27282799
rc = 1;
27292800
}
27302801
sqlite3_close(pDest);
27312802
}else
27322803
27332804
if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
27342805
if( nArg==2 ){
27352806
bail_on_error = booleanValue(azArg[1]);
27362807
}else{
2737
- fprintf(stderr, "Usage: .bail on|off\n");
2808
+ raw_printf(stderr, "Usage: .bail on|off\n");
27382809
rc = 1;
27392810
}
27402811
}else
27412812
27422813
if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
@@ -2745,11 +2816,11 @@
27452816
setBinaryMode(p->out);
27462817
}else{
27472818
setTextMode(p->out);
27482819
}
27492820
}else{
2750
- fprintf(stderr, "Usage: .binary on|off\n");
2821
+ raw_printf(stderr, "Usage: .binary on|off\n");
27512822
rc = 1;
27522823
}
27532824
}else
27542825
27552826
/* The undocumented ".breakpoint" command causes a call to the no-op
@@ -2761,20 +2832,20 @@
27612832
27622833
if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
27632834
if( nArg==2 ){
27642835
p->countChanges = booleanValue(azArg[1]);
27652836
}else{
2766
- fprintf(stderr, "Usage: .changes on|off\n");
2837
+ raw_printf(stderr, "Usage: .changes on|off\n");
27672838
rc = 1;
27682839
}
27692840
}else
27702841
27712842
if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
27722843
if( nArg==2 ){
27732844
tryToClone(p, azArg[1]);
27742845
}else{
2775
- fprintf(stderr, "Usage: .clone FILENAME\n");
2846
+ raw_printf(stderr, "Usage: .clone FILENAME\n");
27762847
rc = 1;
27772848
}
27782849
}else
27792850
27802851
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
@@ -2788,11 +2859,11 @@
27882859
data.colWidth[1] = 15;
27892860
data.colWidth[2] = 58;
27902861
data.cnt = 0;
27912862
sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
27922863
if( zErrMsg ){
2793
- fprintf(stderr,"Error: %s\n", zErrMsg);
2864
+ utf8_printf(stderr,"Error: %s\n", zErrMsg);
27942865
sqlite3_free(zErrMsg);
27952866
rc = 1;
27962867
}
27972868
}else
27982869
@@ -2804,16 +2875,16 @@
28042875
open_db(p, 0);
28052876
/* When playing back a "dump", the content might appear in an order
28062877
** which causes immediate foreign key constraints to be violated.
28072878
** So disable foreign-key constraint enforcement to prevent problems. */
28082879
if( nArg!=1 && nArg!=2 ){
2809
- fprintf(stderr, "Usage: .dump ?LIKE-PATTERN?\n");
2880
+ raw_printf(stderr, "Usage: .dump ?LIKE-PATTERN?\n");
28102881
rc = 1;
28112882
goto meta_command_exit;
28122883
}
2813
- fprintf(p->out, "PRAGMA foreign_keys=OFF;\n");
2814
- fprintf(p->out, "BEGIN TRANSACTION;\n");
2884
+ raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
2885
+ raw_printf(p->out, "BEGIN TRANSACTION;\n");
28152886
p->writableSchema = 0;
28162887
sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
28172888
p->nErr = 0;
28182889
if( nArg==1 ){
28192890
run_schema_dump_query(p,
@@ -2844,32 +2915,32 @@
28442915
);
28452916
zShellStatic = 0;
28462917
}
28472918
}
28482919
if( p->writableSchema ){
2849
- fprintf(p->out, "PRAGMA writable_schema=OFF;\n");
2920
+ raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
28502921
p->writableSchema = 0;
28512922
}
28522923
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
28532924
sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
2854
- fprintf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
2925
+ raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
28552926
}else
28562927
28572928
if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
28582929
if( nArg==2 ){
28592930
p->echoOn = booleanValue(azArg[1]);
28602931
}else{
2861
- fprintf(stderr, "Usage: .echo on|off\n");
2932
+ raw_printf(stderr, "Usage: .echo on|off\n");
28622933
rc = 1;
28632934
}
28642935
}else
28652936
28662937
if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
28672938
if( nArg==2 ){
28682939
p->autoEQP = booleanValue(azArg[1]);
28692940
}else{
2870
- fprintf(stderr, "Usage: .eqp on|off\n");
2941
+ raw_printf(stderr, "Usage: .eqp on|off\n");
28712942
rc = 1;
28722943
}
28732944
}else
28742945
28752946
if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
@@ -2915,11 +2986,11 @@
29152986
if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
29162987
ShellState data;
29172988
char *zErrMsg = 0;
29182989
int doStats = 0;
29192990
if( nArg!=1 ){
2920
- fprintf(stderr, "Usage: .fullschema\n");
2991
+ raw_printf(stderr, "Usage: .fullschema\n");
29212992
rc = 1;
29222993
goto meta_command_exit;
29232994
}
29242995
open_db(p, 0);
29252996
memcpy(&data, p, sizeof(data));
@@ -2942,13 +3013,13 @@
29423013
-1, &pStmt, 0);
29433014
doStats = sqlite3_step(pStmt)==SQLITE_ROW;
29443015
sqlite3_finalize(pStmt);
29453016
}
29463017
if( doStats==0 ){
2947
- fprintf(p->out, "/* No STAT tables available */\n");
3018
+ raw_printf(p->out, "/* No STAT tables available */\n");
29483019
}else{
2949
- fprintf(p->out, "ANALYZE sqlite_master;\n");
3020
+ raw_printf(p->out, "ANALYZE sqlite_master;\n");
29503021
sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'",
29513022
callback, &data, &zErrMsg);
29523023
data.mode = MODE_Insert;
29533024
data.zDestTable = "sqlite_stat1";
29543025
shell_exec(p->db, "SELECT * FROM sqlite_stat1",
@@ -2957,25 +3028,25 @@
29573028
shell_exec(p->db, "SELECT * FROM sqlite_stat3",
29583029
shell_callback, &data,&zErrMsg);
29593030
data.zDestTable = "sqlite_stat4";
29603031
shell_exec(p->db, "SELECT * FROM sqlite_stat4",
29613032
shell_callback, &data, &zErrMsg);
2962
- fprintf(p->out, "ANALYZE sqlite_master;\n");
3033
+ raw_printf(p->out, "ANALYZE sqlite_master;\n");
29633034
}
29643035
}else
29653036
29663037
if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
29673038
if( nArg==2 ){
29683039
p->showHeader = booleanValue(azArg[1]);
29693040
}else{
2970
- fprintf(stderr, "Usage: .headers on|off\n");
3041
+ raw_printf(stderr, "Usage: .headers on|off\n");
29713042
rc = 1;
29723043
}
29733044
}else
29743045
29753046
if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
2976
- fprintf(p->out, "%s", zHelp);
3047
+ utf8_printf(p->out, "%s", zHelp);
29773048
}else
29783049
29793050
if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
29803051
char *zTable; /* Insert data into this table */
29813052
char *zFile; /* Name of file to extra content from */
@@ -2989,31 +3060,32 @@
29893060
ImportCtx sCtx; /* Reader context */
29903061
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
29913062
int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close file */
29923063
29933064
if( nArg!=3 ){
2994
- fprintf(stderr, "Usage: .import FILE TABLE\n");
3065
+ raw_printf(stderr, "Usage: .import FILE TABLE\n");
29953066
goto meta_command_exit;
29963067
}
29973068
zFile = azArg[1];
29983069
zTable = azArg[2];
29993070
seenInterrupt = 0;
30003071
memset(&sCtx, 0, sizeof(sCtx));
30013072
open_db(p, 0);
30023073
nSep = strlen30(p->colSeparator);
30033074
if( nSep==0 ){
3004
- fprintf(stderr, "Error: non-null column separator required for import\n");
3075
+ raw_printf(stderr,
3076
+ "Error: non-null column separator required for import\n");
30053077
return 1;
30063078
}
30073079
if( nSep>1 ){
3008
- fprintf(stderr, "Error: multi-character column separators not allowed"
3080
+ raw_printf(stderr, "Error: multi-character column separators not allowed"
30093081
" for import\n");
30103082
return 1;
30113083
}
30123084
nSep = strlen30(p->rowSeparator);
30133085
if( nSep==0 ){
3014
- fprintf(stderr, "Error: non-null row separator required for import\n");
3086
+ raw_printf(stderr, "Error: non-null row separator required for import\n");
30153087
return 1;
30163088
}
30173089
if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){
30183090
/* When importing CSV (only), if the row separator is set to the
30193091
** default output row separator, change it to the default input
@@ -3021,19 +3093,19 @@
30213093
** and output row separators. */
30223094
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
30233095
nSep = strlen30(p->rowSeparator);
30243096
}
30253097
if( nSep>1 ){
3026
- fprintf(stderr, "Error: multi-character row separators not allowed"
3098
+ raw_printf(stderr, "Error: multi-character row separators not allowed"
30273099
" for import\n");
30283100
return 1;
30293101
}
30303102
sCtx.zFile = zFile;
30313103
sCtx.nLine = 1;
30323104
if( sCtx.zFile[0]=='|' ){
30333105
#ifdef SQLITE_OMIT_POPEN
3034
- fprintf(stderr, "Error: pipes are not supported in this OS\n");
3106
+ raw_printf(stderr, "Error: pipes are not supported in this OS\n");
30353107
return 1;
30363108
#else
30373109
sCtx.in = popen(sCtx.zFile+1, "r");
30383110
sCtx.zFile = "<pipe>";
30393111
xCloser = pclose;
@@ -3046,18 +3118,18 @@
30463118
xRead = ascii_read_one_field;
30473119
}else{
30483120
xRead = csv_read_one_field;
30493121
}
30503122
if( sCtx.in==0 ){
3051
- fprintf(stderr, "Error: cannot open \"%s\"\n", zFile);
3123
+ utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
30523124
return 1;
30533125
}
30543126
sCtx.cColSep = p->colSeparator[0];
30553127
sCtx.cRowSep = p->rowSeparator[0];
30563128
zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
30573129
if( zSql==0 ){
3058
- fprintf(stderr, "Error: out of memory\n");
3130
+ raw_printf(stderr, "Error: out of memory\n");
30593131
xCloser(sCtx.in);
30603132
return 1;
30613133
}
30623134
nByte = strlen30(zSql);
30633135
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
@@ -3072,18 +3144,18 @@
30723144
}
30733145
if( cSep=='(' ){
30743146
sqlite3_free(zCreate);
30753147
sqlite3_free(sCtx.z);
30763148
xCloser(sCtx.in);
3077
- fprintf(stderr,"%s: empty file\n", sCtx.zFile);
3149
+ utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
30783150
return 1;
30793151
}
30803152
zCreate = sqlite3_mprintf("%z\n)", zCreate);
30813153
rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
30823154
sqlite3_free(zCreate);
30833155
if( rc ){
3084
- fprintf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
3156
+ utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
30853157
sqlite3_errmsg(p->db));
30863158
sqlite3_free(sCtx.z);
30873159
xCloser(sCtx.in);
30883160
return 1;
30893161
}
@@ -3090,21 +3162,21 @@
30903162
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
30913163
}
30923164
sqlite3_free(zSql);
30933165
if( rc ){
30943166
if (pStmt) sqlite3_finalize(pStmt);
3095
- fprintf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
3167
+ utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
30963168
xCloser(sCtx.in);
30973169
return 1;
30983170
}
30993171
nCol = sqlite3_column_count(pStmt);
31003172
sqlite3_finalize(pStmt);
31013173
pStmt = 0;
31023174
if( nCol==0 ) return 0; /* no columns, no error */
31033175
zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
31043176
if( zSql==0 ){
3105
- fprintf(stderr, "Error: out of memory\n");
3177
+ raw_printf(stderr, "Error: out of memory\n");
31063178
xCloser(sCtx.in);
31073179
return 1;
31083180
}
31093181
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
31103182
j = strlen30(zSql);
@@ -3115,11 +3187,11 @@
31153187
zSql[j++] = ')';
31163188
zSql[j] = 0;
31173189
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
31183190
sqlite3_free(zSql);
31193191
if( rc ){
3120
- fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
3192
+ utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
31213193
if (pStmt) sqlite3_finalize(pStmt);
31223194
xCloser(sCtx.in);
31233195
return 1;
31243196
}
31253197
needCommit = sqlite3_get_autocommit(p->db);
@@ -3139,11 +3211,11 @@
31393211
** the remaining columns.
31403212
*/
31413213
if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
31423214
sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
31433215
if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
3144
- fprintf(stderr, "%s:%d: expected %d columns but found %d - "
3216
+ utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
31453217
"filling the rest with NULL\n",
31463218
sCtx.zFile, startLine, nCol, i+1);
31473219
i += 2;
31483220
while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
31493221
}
@@ -3151,20 +3223,20 @@
31513223
if( sCtx.cTerm==sCtx.cColSep ){
31523224
do{
31533225
xRead(&sCtx);
31543226
i++;
31553227
}while( sCtx.cTerm==sCtx.cColSep );
3156
- fprintf(stderr, "%s:%d: expected %d columns but found %d - "
3228
+ utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
31573229
"extras ignored\n",
31583230
sCtx.zFile, startLine, nCol, i);
31593231
}
31603232
if( i>=nCol ){
31613233
sqlite3_step(pStmt);
31623234
rc = sqlite3_reset(pStmt);
31633235
if( rc!=SQLITE_OK ){
3164
- fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile, startLine,
3165
- sqlite3_errmsg(p->db));
3236
+ utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
3237
+ startLine, sqlite3_errmsg(p->db));
31663238
}
31673239
}
31683240
}while( sCtx.cTerm!=EOF );
31693241
31703242
xCloser(sCtx.in);
@@ -3202,20 +3274,21 @@
32023274
"ORDER BY 1",
32033275
callback, &data, &zErrMsg
32043276
);
32053277
zShellStatic = 0;
32063278
}else{
3207
- fprintf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
3279
+ raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
32083280
rc = 1;
32093281
goto meta_command_exit;
32103282
}
32113283
if( zErrMsg ){
3212
- fprintf(stderr,"Error: %s\n", zErrMsg);
3284
+ utf8_printf(stderr,"Error: %s\n", zErrMsg);
32133285
sqlite3_free(zErrMsg);
32143286
rc = 1;
32153287
}else if( rc != SQLITE_OK ){
3216
- fprintf(stderr,"Error: querying sqlite_master and sqlite_temp_master\n");
3288
+ raw_printf(stderr,
3289
+ "Error: querying sqlite_master and sqlite_temp_master\n");
32173290
rc = 1;
32183291
}
32193292
}else
32203293
32213294
#ifdef SQLITE_ENABLE_IOTRACE
@@ -3229,11 +3302,11 @@
32293302
sqlite3IoTrace = iotracePrintf;
32303303
iotrace = stdout;
32313304
}else{
32323305
iotrace = fopen(azArg[1], "w");
32333306
if( iotrace==0 ){
3234
- fprintf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
3307
+ utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
32353308
sqlite3IoTrace = 0;
32363309
rc = 1;
32373310
}else{
32383311
sqlite3IoTrace = iotracePrintf;
32393312
}
@@ -3264,11 +3337,11 @@
32643337
for(i=0; i<ArraySize(aLimit); i++){
32653338
printf("%20s %d\n", aLimit[i].zLimitName,
32663339
sqlite3_limit(p->db, aLimit[i].limitCode, -1));
32673340
}
32683341
}else if( nArg>3 ){
3269
- fprintf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
3342
+ raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
32703343
rc = 1;
32713344
goto meta_command_exit;
32723345
}else{
32733346
int iLimit = -1;
32743347
n2 = strlen30(azArg[1]);
@@ -3275,18 +3348,18 @@
32753348
for(i=0; i<ArraySize(aLimit); i++){
32763349
if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
32773350
if( iLimit<0 ){
32783351
iLimit = i;
32793352
}else{
3280
- fprintf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
3353
+ utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
32813354
rc = 1;
32823355
goto meta_command_exit;
32833356
}
32843357
}
32853358
}
32863359
if( iLimit<0 ){
3287
- fprintf(stderr, "unknown limit: \"%s\"\n"
3360
+ utf8_printf(stderr, "unknown limit: \"%s\"\n"
32883361
"enter \".limits\" with no arguments for a list.\n",
32893362
azArg[1]);
32903363
rc = 1;
32913364
goto meta_command_exit;
32923365
}
@@ -3302,29 +3375,29 @@
33023375
#ifndef SQLITE_OMIT_LOAD_EXTENSION
33033376
if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
33043377
const char *zFile, *zProc;
33053378
char *zErrMsg = 0;
33063379
if( nArg<2 ){
3307
- fprintf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
3380
+ raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
33083381
rc = 1;
33093382
goto meta_command_exit;
33103383
}
33113384
zFile = azArg[1];
33123385
zProc = nArg>=3 ? azArg[2] : 0;
33133386
open_db(p, 0);
33143387
rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
33153388
if( rc!=SQLITE_OK ){
3316
- fprintf(stderr, "Error: %s\n", zErrMsg);
3389
+ utf8_printf(stderr, "Error: %s\n", zErrMsg);
33173390
sqlite3_free(zErrMsg);
33183391
rc = 1;
33193392
}
33203393
}else
33213394
#endif
33223395
33233396
if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
33243397
if( nArg!=2 ){
3325
- fprintf(stderr, "Usage: .log FILENAME\n");
3398
+ raw_printf(stderr, "Usage: .log FILENAME\n");
33263399
rc = 1;
33273400
}else{
33283401
const char *zFile = azArg[1];
33293402
output_file_close(p->pLog);
33303403
p->pLog = output_file_open(zFile);
@@ -3359,11 +3432,11 @@
33593432
}else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
33603433
p->mode = MODE_Ascii;
33613434
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
33623435
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
33633436
}else {
3364
- fprintf(stderr,"Error: mode should be one of: "
3437
+ raw_printf(stderr, "Error: mode should be one of: "
33653438
"ascii column csv html insert line list tabs tcl\n");
33663439
rc = 1;
33673440
}
33683441
}else
33693442
@@ -3370,11 +3443,11 @@
33703443
if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
33713444
if( nArg==2 ){
33723445
sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
33733446
"%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
33743447
}else{
3375
- fprintf(stderr, "Usage: .nullvalue STRING\n");
3448
+ raw_printf(stderr, "Usage: .nullvalue STRING\n");
33763449
rc = 1;
33773450
}
33783451
}else
33793452
33803453
if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
@@ -3399,17 +3472,17 @@
33993472
if( c=='o'
34003473
&& (strncmp(azArg[0], "output", n)==0 || strncmp(azArg[0], "once", n)==0)
34013474
){
34023475
const char *zFile = nArg>=2 ? azArg[1] : "stdout";
34033476
if( nArg>2 ){
3404
- fprintf(stderr, "Usage: .%s FILE\n", azArg[0]);
3477
+ utf8_printf(stderr, "Usage: .%s FILE\n", azArg[0]);
34053478
rc = 1;
34063479
goto meta_command_exit;
34073480
}
34083481
if( n>1 && strncmp(azArg[0], "once", n)==0 ){
34093482
if( nArg<2 ){
3410
- fprintf(stderr, "Usage: .once FILE\n");
3483
+ raw_printf(stderr, "Usage: .once FILE\n");
34113484
rc = 1;
34123485
goto meta_command_exit;
34133486
}
34143487
p->outCount = 2;
34153488
}else{
@@ -3416,17 +3489,17 @@
34163489
p->outCount = 0;
34173490
}
34183491
output_reset(p);
34193492
if( zFile[0]=='|' ){
34203493
#ifdef SQLITE_OMIT_POPEN
3421
- fprintf(stderr,"Error: pipes are not supported in this OS\n");
3494
+ raw_printf(stderr, "Error: pipes are not supported in this OS\n");
34223495
rc = 1;
34233496
p->out = stdout;
34243497
#else
34253498
p->out = popen(zFile + 1, "w");
34263499
if( p->out==0 ){
3427
- fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
3500
+ utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
34283501
p->out = stdout;
34293502
rc = 1;
34303503
}else{
34313504
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
34323505
}
@@ -3433,11 +3506,11 @@
34333506
#endif
34343507
}else{
34353508
p->out = output_file_open(zFile);
34363509
if( p->out==0 ){
34373510
if( strcmp(zFile,"off")!=0 ){
3438
- fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile);
3511
+ utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
34393512
}
34403513
p->out = stdout;
34413514
rc = 1;
34423515
} else {
34433516
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
@@ -3446,14 +3519,14 @@
34463519
}else
34473520
34483521
if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
34493522
int i;
34503523
for(i=1; i<nArg; i++){
3451
- if( i>1 ) fprintf(p->out, " ");
3452
- fprintf(p->out, "%s", azArg[i]);
3524
+ if( i>1 ) raw_printf(p->out, " ");
3525
+ utf8_printf(p->out, "%s", azArg[i]);
34533526
}
3454
- fprintf(p->out, "\n");
3527
+ raw_printf(p->out, "\n");
34553528
}else
34563529
34573530
if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
34583531
if( nArg >= 2) {
34593532
strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
@@ -3468,17 +3541,17 @@
34683541
}else
34693542
34703543
if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
34713544
FILE *alt;
34723545
if( nArg!=2 ){
3473
- fprintf(stderr, "Usage: .read FILE\n");
3546
+ raw_printf(stderr, "Usage: .read FILE\n");
34743547
rc = 1;
34753548
goto meta_command_exit;
34763549
}
34773550
alt = fopen(azArg[1], "rb");
34783551
if( alt==0 ){
3479
- fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
3552
+ utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
34803553
rc = 1;
34813554
}else{
34823555
rc = process_input(p, alt);
34833556
fclose(alt);
34843557
}
@@ -3496,24 +3569,24 @@
34963569
zDb = "main";
34973570
}else if( nArg==3 ){
34983571
zSrcFile = azArg[2];
34993572
zDb = azArg[1];
35003573
}else{
3501
- fprintf(stderr, "Usage: .restore ?DB? FILE\n");
3574
+ raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
35023575
rc = 1;
35033576
goto meta_command_exit;
35043577
}
35053578
rc = sqlite3_open(zSrcFile, &pSrc);
35063579
if( rc!=SQLITE_OK ){
3507
- fprintf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
3580
+ utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
35083581
sqlite3_close(pSrc);
35093582
return 1;
35103583
}
35113584
open_db(p, 0);
35123585
pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
35133586
if( pBackup==0 ){
3514
- fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
3587
+ utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
35153588
sqlite3_close(pSrc);
35163589
return 1;
35173590
}
35183591
while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
35193592
|| rc==SQLITE_BUSY ){
@@ -3524,14 +3597,14 @@
35243597
}
35253598
sqlite3_backup_finish(pBackup);
35263599
if( rc==SQLITE_DONE ){
35273600
rc = 0;
35283601
}else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
3529
- fprintf(stderr, "Error: source database is busy\n");
3602
+ raw_printf(stderr, "Error: source database is busy\n");
35303603
rc = 1;
35313604
}else{
3532
- fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
3605
+ utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
35333606
rc = 1;
35343607
}
35353608
sqlite3_close(pSrc);
35363609
}else
35373610
@@ -3538,14 +3611,14 @@
35383611
35393612
if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
35403613
if( nArg==2 ){
35413614
p->scanstatsOn = booleanValue(azArg[1]);
35423615
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
3543
- fprintf(stderr, "Warning: .scanstats not available in this build.\n");
3616
+ raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
35443617
#endif
35453618
}else{
3546
- fprintf(stderr, "Usage: .scanstats on|off\n");
3619
+ raw_printf(stderr, "Usage: .scanstats on|off\n");
35473620
rc = 1;
35483621
}
35493622
}else
35503623
35513624
if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
@@ -3608,20 +3681,20 @@
36083681
"WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
36093682
"ORDER BY rowid",
36103683
callback, &data, &zErrMsg
36113684
);
36123685
}else{
3613
- fprintf(stderr, "Usage: .schema ?LIKE-PATTERN?\n");
3686
+ raw_printf(stderr, "Usage: .schema ?LIKE-PATTERN?\n");
36143687
rc = 1;
36153688
goto meta_command_exit;
36163689
}
36173690
if( zErrMsg ){
3618
- fprintf(stderr,"Error: %s\n", zErrMsg);
3691
+ utf8_printf(stderr,"Error: %s\n", zErrMsg);
36193692
sqlite3_free(zErrMsg);
36203693
rc = 1;
36213694
}else if( rc != SQLITE_OK ){
3622
- fprintf(stderr,"Error: querying schema information\n");
3695
+ raw_printf(stderr,"Error: querying schema information\n");
36233696
rc = 1;
36243697
}else{
36253698
rc = 0;
36263699
}
36273700
}else
@@ -3641,28 +3714,28 @@
36413714
if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
36423715
if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
36433716
int i, v;
36443717
for(i=1; i<nArg; i++){
36453718
v = booleanValue(azArg[i]);
3646
- fprintf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
3719
+ utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
36473720
}
36483721
}
36493722
if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
36503723
int i; sqlite3_int64 v;
36513724
for(i=1; i<nArg; i++){
36523725
char zBuf[200];
36533726
v = integerValue(azArg[i]);
36543727
sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
3655
- fprintf(p->out, "%s", zBuf);
3728
+ utf8_printf(p->out, "%s", zBuf);
36563729
}
36573730
}
36583731
}else
36593732
#endif
36603733
36613734
if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
36623735
if( nArg<2 || nArg>3 ){
3663
- fprintf(stderr, "Usage: .separator COL ?ROW?\n");
3736
+ raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
36643737
rc = 1;
36653738
}
36663739
if( nArg>=2 ){
36673740
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
36683741
"%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
@@ -3677,11 +3750,11 @@
36773750
&& (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
36783751
){
36793752
char *zCmd;
36803753
int i, x;
36813754
if( nArg<2 ){
3682
- fprintf(stderr, "Usage: .system COMMAND\n");
3755
+ raw_printf(stderr, "Usage: .system COMMAND\n");
36833756
rc = 1;
36843757
goto meta_command_exit;
36853758
}
36863759
zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
36873760
for(i=2; i<nArg; i++){
@@ -3688,49 +3761,49 @@
36883761
zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
36893762
zCmd, azArg[i]);
36903763
}
36913764
x = system(zCmd);
36923765
sqlite3_free(zCmd);
3693
- if( x ) fprintf(stderr, "System command returns %d\n", x);
3766
+ if( x ) raw_printf(stderr, "System command returns %d\n", x);
36943767
}else
36953768
36963769
if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
36973770
int i;
36983771
if( nArg!=1 ){
3699
- fprintf(stderr, "Usage: .show\n");
3772
+ raw_printf(stderr, "Usage: .show\n");
37003773
rc = 1;
37013774
goto meta_command_exit;
37023775
}
3703
- fprintf(p->out,"%12.12s: %s\n","echo", p->echoOn ? "on" : "off");
3704
- fprintf(p->out,"%12.12s: %s\n","eqp", p->autoEQP ? "on" : "off");
3705
- fprintf(p->out,"%9.9s: %s\n","explain", p->normalMode.valid ? "on" :"off");
3706
- fprintf(p->out,"%12.12s: %s\n","headers", p->showHeader ? "on" : "off");
3707
- fprintf(p->out,"%12.12s: %s\n","mode", modeDescr[p->mode]);
3708
- fprintf(p->out,"%12.12s: ", "nullvalue");
3776
+ utf8_printf(p->out, "%12.12s: %s\n","echo", p->echoOn ? "on" : "off");
3777
+ utf8_printf(p->out, "%12.12s: %s\n","eqp", p->autoEQP ? "on" : "off");
3778
+ utf8_printf(p->out,"%9.9s: %s\n","explain",p->normalMode.valid?"on":"off");
3779
+ utf8_printf(p->out,"%12.12s: %s\n","headers", p->showHeader ? "on" : "off");
3780
+ utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
3781
+ utf8_printf(p->out, "%12.12s: ", "nullvalue");
37093782
output_c_string(p->out, p->nullValue);
3710
- fprintf(p->out, "\n");
3711
- fprintf(p->out,"%12.12s: %s\n","output",
3783
+ raw_printf(p->out, "\n");
3784
+ utf8_printf(p->out,"%12.12s: %s\n","output",
37123785
strlen30(p->outfile) ? p->outfile : "stdout");
3713
- fprintf(p->out,"%12.12s: ", "colseparator");
3786
+ utf8_printf(p->out,"%12.12s: ", "colseparator");
37143787
output_c_string(p->out, p->colSeparator);
3715
- fprintf(p->out, "\n");
3716
- fprintf(p->out,"%12.12s: ", "rowseparator");
3788
+ raw_printf(p->out, "\n");
3789
+ utf8_printf(p->out,"%12.12s: ", "rowseparator");
37173790
output_c_string(p->out, p->rowSeparator);
3718
- fprintf(p->out, "\n");
3719
- fprintf(p->out,"%12.12s: %s\n","stats", p->statsOn ? "on" : "off");
3720
- fprintf(p->out,"%12.12s: ","width");
3791
+ raw_printf(p->out, "\n");
3792
+ utf8_printf(p->out, "%12.12s: %s\n","stats", p->statsOn ? "on" : "off");
3793
+ utf8_printf(p->out, "%12.12s: ", "width");
37213794
for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
3722
- fprintf(p->out,"%d ",p->colWidth[i]);
3795
+ raw_printf(p->out, "%d ", p->colWidth[i]);
37233796
}
3724
- fprintf(p->out,"\n");
3797
+ raw_printf(p->out, "\n");
37253798
}else
37263799
37273800
if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
37283801
if( nArg==2 ){
37293802
p->statsOn = booleanValue(azArg[1]);
37303803
}else{
3731
- fprintf(stderr, "Usage: .stats on|off\n");
3804
+ raw_printf(stderr, "Usage: .stats on|off\n");
37323805
rc = 1;
37333806
}
37343807
}else
37353808
37363809
if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
@@ -3824,13 +3897,14 @@
38243897
if( nPrintCol<1 ) nPrintCol = 1;
38253898
nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
38263899
for(i=0; i<nPrintRow; i++){
38273900
for(j=i; j<nRow; j+=nPrintRow){
38283901
char *zSp = j<nPrintRow ? "" : " ";
3829
- fprintf(p->out, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:"");
3902
+ utf8_printf(p->out, "%s%-*s", zSp, maxlen,
3903
+ azResult[j] ? azResult[j]:"");
38303904
}
3831
- fprintf(p->out, "\n");
3905
+ raw_printf(p->out, "\n");
38323906
}
38333907
}
38343908
38353909
for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
38363910
sqlite3_free(azResult);
@@ -3869,31 +3943,31 @@
38693943
for(i=0; i<ArraySize(aCtrl); i++){
38703944
if( strncmp(azArg[1], aCtrl[i].zCtrlName, n2)==0 ){
38713945
if( testctrl<0 ){
38723946
testctrl = aCtrl[i].ctrlCode;
38733947
}else{
3874
- fprintf(stderr, "ambiguous option name: \"%s\"\n", azArg[1]);
3948
+ utf8_printf(stderr, "ambiguous option name: \"%s\"\n", azArg[1]);
38753949
testctrl = -1;
38763950
break;
38773951
}
38783952
}
38793953
}
38803954
if( testctrl<0 ) testctrl = (int)integerValue(azArg[1]);
38813955
if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){
3882
- fprintf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]);
3956
+ utf8_printf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]);
38833957
}else{
38843958
switch(testctrl){
38853959
38863960
/* sqlite3_test_control(int, db, int) */
38873961
case SQLITE_TESTCTRL_OPTIMIZATIONS:
38883962
case SQLITE_TESTCTRL_RESERVE:
38893963
if( nArg==3 ){
38903964
int opt = (int)strtol(azArg[2], 0, 0);
38913965
rc2 = sqlite3_test_control(testctrl, p->db, opt);
3892
- fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
3966
+ raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
38933967
} else {
3894
- fprintf(stderr,"Error: testctrl %s takes a single int option\n",
3968
+ utf8_printf(stderr,"Error: testctrl %s takes a single int option\n",
38953969
azArg[1]);
38963970
}
38973971
break;
38983972
38993973
/* sqlite3_test_control(int) */
@@ -3901,24 +3975,25 @@
39013975
case SQLITE_TESTCTRL_PRNG_RESTORE:
39023976
case SQLITE_TESTCTRL_PRNG_RESET:
39033977
case SQLITE_TESTCTRL_BYTEORDER:
39043978
if( nArg==2 ){
39053979
rc2 = sqlite3_test_control(testctrl);
3906
- fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
3980
+ raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
39073981
} else {
3908
- fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]);
3982
+ utf8_printf(stderr,"Error: testctrl %s takes no options\n",
3983
+ azArg[1]);
39093984
}
39103985
break;
39113986
39123987
/* sqlite3_test_control(int, uint) */
39133988
case SQLITE_TESTCTRL_PENDING_BYTE:
39143989
if( nArg==3 ){
39153990
unsigned int opt = (unsigned int)integerValue(azArg[2]);
39163991
rc2 = sqlite3_test_control(testctrl, opt);
3917
- fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
3992
+ raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
39183993
} else {
3919
- fprintf(stderr,"Error: testctrl %s takes a single unsigned"
3994
+ utf8_printf(stderr,"Error: testctrl %s takes a single unsigned"
39203995
" int option\n", azArg[1]);
39213996
}
39223997
break;
39233998
39243999
/* sqlite3_test_control(int, int) */
@@ -3926,13 +4001,13 @@
39264001
case SQLITE_TESTCTRL_ALWAYS:
39274002
case SQLITE_TESTCTRL_NEVER_CORRUPT:
39284003
if( nArg==3 ){
39294004
int opt = booleanValue(azArg[2]);
39304005
rc2 = sqlite3_test_control(testctrl, opt);
3931
- fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
4006
+ raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
39324007
} else {
3933
- fprintf(stderr,"Error: testctrl %s takes a single int option\n",
4008
+ utf8_printf(stderr,"Error: testctrl %s takes a single int option\n",
39344009
azArg[1]);
39354010
}
39364011
break;
39374012
39384013
/* sqlite3_test_control(int, char *) */
@@ -3939,14 +4014,15 @@
39394014
#ifdef SQLITE_N_KEYWORD
39404015
case SQLITE_TESTCTRL_ISKEYWORD:
39414016
if( nArg==3 ){
39424017
const char *opt = azArg[2];
39434018
rc2 = sqlite3_test_control(testctrl, opt);
3944
- fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
4019
+ raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
39454020
} else {
3946
- fprintf(stderr,"Error: testctrl %s takes a single char * option\n",
3947
- azArg[1]);
4021
+ utf8_printf(stderr,
4022
+ "Error: testctrl %s takes a single char * option\n",
4023
+ azArg[1]);
39484024
}
39494025
break;
39504026
#endif
39514027
39524028
case SQLITE_TESTCTRL_IMPOSTER:
@@ -3953,23 +4029,24 @@
39534029
if( nArg==5 ){
39544030
rc2 = sqlite3_test_control(testctrl, p->db,
39554031
azArg[2],
39564032
integerValue(azArg[3]),
39574033
integerValue(azArg[4]));
3958
- fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
4034
+ raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
39594035
}else{
3960
- fprintf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
4036
+ raw_printf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
39614037
}
39624038
break;
39634039
39644040
case SQLITE_TESTCTRL_BITVEC_TEST:
39654041
case SQLITE_TESTCTRL_FAULT_INSTALL:
39664042
case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
39674043
case SQLITE_TESTCTRL_SCRATCHMALLOC:
39684044
default:
3969
- fprintf(stderr,"Error: CLI support for testctrl %s not implemented\n",
3970
- azArg[1]);
4045
+ utf8_printf(stderr,
4046
+ "Error: CLI support for testctrl %s not implemented\n",
4047
+ azArg[1]);
39714048
break;
39724049
}
39734050
}
39744051
}else
39754052
@@ -3980,23 +4057,23 @@
39804057
39814058
if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
39824059
if( nArg==2 ){
39834060
enableTimer = booleanValue(azArg[1]);
39844061
if( enableTimer && !HAS_TIMER ){
3985
- fprintf(stderr, "Error: timer not available on this system.\n");
4062
+ raw_printf(stderr, "Error: timer not available on this system.\n");
39864063
enableTimer = 0;
39874064
}
39884065
}else{
3989
- fprintf(stderr, "Usage: .timer on|off\n");
4066
+ raw_printf(stderr, "Usage: .timer on|off\n");
39904067
rc = 1;
39914068
}
39924069
}else
39934070
39944071
if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
39954072
open_db(p, 0);
39964073
if( nArg!=2 ){
3997
- fprintf(stderr, "Usage: .trace FILE|off\n");
4074
+ raw_printf(stderr, "Usage: .trace FILE|off\n");
39984075
rc = 1;
39994076
goto meta_command_exit;
40004077
}
40014078
output_file_close(p->traceOut);
40024079
p->traceOut = output_file_open(azArg[1]);
@@ -4010,87 +4087,87 @@
40104087
}else
40114088
40124089
#if SQLITE_USER_AUTHENTICATION
40134090
if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
40144091
if( nArg<2 ){
4015
- fprintf(stderr, "Usage: .user SUBCOMMAND ...\n");
4092
+ raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
40164093
rc = 1;
40174094
goto meta_command_exit;
40184095
}
40194096
open_db(p, 0);
40204097
if( strcmp(azArg[1],"login")==0 ){
40214098
if( nArg!=4 ){
4022
- fprintf(stderr, "Usage: .user login USER PASSWORD\n");
4099
+ raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
40234100
rc = 1;
40244101
goto meta_command_exit;
40254102
}
40264103
rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
40274104
(int)strlen(azArg[3]));
40284105
if( rc ){
4029
- fprintf(stderr, "Authentication failed for user %s\n", azArg[2]);
4106
+ utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
40304107
rc = 1;
40314108
}
40324109
}else if( strcmp(azArg[1],"add")==0 ){
40334110
if( nArg!=5 ){
4034
- fprintf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
4111
+ raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
40354112
rc = 1;
40364113
goto meta_command_exit;
40374114
}
40384115
rc = sqlite3_user_add(p->db, azArg[2],
40394116
azArg[3], (int)strlen(azArg[3]),
40404117
booleanValue(azArg[4]));
40414118
if( rc ){
4042
- fprintf(stderr, "User-Add failed: %d\n", rc);
4119
+ raw_printf(stderr, "User-Add failed: %d\n", rc);
40434120
rc = 1;
40444121
}
40454122
}else if( strcmp(azArg[1],"edit")==0 ){
40464123
if( nArg!=5 ){
4047
- fprintf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
4124
+ raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
40484125
rc = 1;
40494126
goto meta_command_exit;
40504127
}
40514128
rc = sqlite3_user_change(p->db, azArg[2],
40524129
azArg[3], (int)strlen(azArg[3]),
40534130
booleanValue(azArg[4]));
40544131
if( rc ){
4055
- fprintf(stderr, "User-Edit failed: %d\n", rc);
4132
+ raw_printf(stderr, "User-Edit failed: %d\n", rc);
40564133
rc = 1;
40574134
}
40584135
}else if( strcmp(azArg[1],"delete")==0 ){
40594136
if( nArg!=3 ){
4060
- fprintf(stderr, "Usage: .user delete USER\n");
4137
+ raw_printf(stderr, "Usage: .user delete USER\n");
40614138
rc = 1;
40624139
goto meta_command_exit;
40634140
}
40644141
rc = sqlite3_user_delete(p->db, azArg[2]);
40654142
if( rc ){
4066
- fprintf(stderr, "User-Delete failed: %d\n", rc);
4143
+ raw_printf(stderr, "User-Delete failed: %d\n", rc);
40674144
rc = 1;
40684145
}
40694146
}else{
4070
- fprintf(stderr, "Usage: .user login|add|edit|delete ...\n");
4147
+ raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
40714148
rc = 1;
40724149
goto meta_command_exit;
40734150
}
40744151
}else
40754152
#endif /* SQLITE_USER_AUTHENTICATION */
40764153
40774154
if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
4078
- fprintf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
4155
+ utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
40794156
sqlite3_libversion(), sqlite3_sourceid());
40804157
}else
40814158
40824159
if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
40834160
const char *zDbName = nArg==2 ? azArg[1] : "main";
40844161
sqlite3_vfs *pVfs;
40854162
if( p->db ){
40864163
sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
40874164
if( pVfs ){
4088
- fprintf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
4089
- fprintf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
4090
- fprintf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
4091
- fprintf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
4165
+ utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
4166
+ raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
4167
+ raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
4168
+ raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
40924169
}
40934170
}
40944171
}else
40954172
40964173
if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
@@ -4097,11 +4174,11 @@
40974174
const char *zDbName = nArg==2 ? azArg[1] : "main";
40984175
char *zVfsName = 0;
40994176
if( p->db ){
41004177
sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
41014178
if( zVfsName ){
4102
- fprintf(p->out, "%s\n", zVfsName);
4179
+ utf8_printf(p->out, "%s\n", zVfsName);
41034180
sqlite3_free(zVfsName);
41044181
}
41054182
}
41064183
}else
41074184
@@ -4119,11 +4196,11 @@
41194196
p->colWidth[j-1] = (int)integerValue(azArg[j]);
41204197
}
41214198
}else
41224199
41234200
{
4124
- fprintf(stderr, "Error: unknown command or invalid arguments: "
4201
+ utf8_printf(stderr, "Error: unknown command or invalid arguments: "
41254202
" \"%s\". Enter \".help\" for help\n", azArg[0]);
41264203
rc = 1;
41274204
}
41284205
41294206
meta_command_exit:
@@ -4254,11 +4331,11 @@
42544331
nLine = strlen30(zLine);
42554332
if( nSql+nLine+2>=nAlloc ){
42564333
nAlloc = nSql+nLine+100;
42574334
zSql = realloc(zSql, nAlloc);
42584335
if( zSql==0 ){
4259
- fprintf(stderr, "Error: out of memory\n");
4336
+ raw_printf(stderr, "Error: out of memory\n");
42604337
exit(1);
42614338
}
42624339
}
42634340
nSqlPrior = nSql;
42644341
if( nSql==0 ){
@@ -4288,19 +4365,19 @@
42884365
"Error: near line %d:", startline);
42894366
}else{
42904367
sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
42914368
}
42924369
if( zErrMsg!=0 ){
4293
- fprintf(stderr, "%s %s\n", zPrefix, zErrMsg);
4370
+ utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
42944371
sqlite3_free(zErrMsg);
42954372
zErrMsg = 0;
42964373
}else{
4297
- fprintf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
4374
+ utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
42984375
}
42994376
errCnt++;
43004377
}else if( p->countChanges ){
4301
- fprintf(p->out, "changes: %3d total_changes: %d\n",
4378
+ raw_printf(p->out, "changes: %3d total_changes: %d\n",
43024379
sqlite3_changes(p->db), sqlite3_total_changes(p->db));
43034380
}
43044381
nSql = 0;
43054382
if( p->outCount ){
43064383
output_reset(p);
@@ -4311,11 +4388,11 @@
43114388
nSql = 0;
43124389
}
43134390
}
43144391
if( nSql ){
43154392
if( !_all_whitespace(zSql) ){
4316
- fprintf(stderr, "Error: incomplete SQL: %s\n", zSql);
4393
+ utf8_printf(stderr, "Error: incomplete SQL: %s\n", zSql);
43174394
errCnt++;
43184395
}
43194396
}
43204397
free(zSql);
43214398
free(zLine);
@@ -4402,11 +4479,11 @@
44024479
FILE *in = NULL;
44034480
44044481
if (sqliterc == NULL) {
44054482
home_dir = find_home_dir();
44064483
if( home_dir==0 ){
4407
- fprintf(stderr, "-- warning: cannot find home directory;"
4484
+ raw_printf(stderr, "-- warning: cannot find home directory;"
44084485
" cannot read ~/.sqliterc\n");
44094486
return;
44104487
}
44114488
sqlite3_initialize();
44124489
zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
@@ -4413,11 +4490,11 @@
44134490
sqliterc = zBuf;
44144491
}
44154492
in = fopen(sqliterc,"rb");
44164493
if( in ){
44174494
if( stdin_is_interactive ){
4418
- fprintf(stderr,"-- Loading resources from %s\n",sqliterc);
4495
+ utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
44194496
}
44204497
process_input(p,in);
44214498
fclose(in);
44224499
}
44234500
sqlite3_free(zBuf);
@@ -4460,18 +4537,18 @@
44604537
#ifdef SQLITE_ENABLE_VFSTRACE
44614538
" -vfstrace enable tracing of all VFS calls\n"
44624539
#endif
44634540
;
44644541
static void usage(int showDetail){
4465
- fprintf(stderr,
4542
+ utf8_printf(stderr,
44664543
"Usage: %s [OPTIONS] FILENAME [SQL]\n"
44674544
"FILENAME is the name of an SQLite database. A new database is created\n"
44684545
"if the file does not previously exist.\n", Argv0);
44694546
if( showDetail ){
4470
- fprintf(stderr, "OPTIONS include:\n%s", zOptions);
4547
+ utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
44714548
}else{
4472
- fprintf(stderr, "Use the -help option for additional information\n");
4549
+ raw_printf(stderr, "Use the -help option for additional information\n");
44734550
}
44744551
exit(1);
44754552
}
44764553
44774554
/*
@@ -4515,11 +4592,11 @@
45154592
** Get the argument to an --option. Throw an error and die if no argument
45164593
** is available.
45174594
*/
45184595
static char *cmdline_option_value(int argc, char **argv, int i){
45194596
if( i==argc ){
4520
- fprintf(stderr, "%s: Error: missing argument to %s\n",
4597
+ utf8_printf(stderr, "%s: Error: missing argument to %s\n",
45214598
argv[0], argv[argc-1]);
45224599
exit(1);
45234600
}
45244601
return argv[i];
45254602
}
@@ -4535,20 +4612,21 @@
45354612
int nCmd = 0;
45364613
char **azCmd = 0;
45374614
45384615
#if USE_SYSTEM_SQLITE+0!=1
45394616
if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
4540
- fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
4617
+ utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
45414618
sqlite3_sourceid(), SQLITE_SOURCE_ID);
45424619
exit(1);
45434620
}
45444621
#endif
45454622
setBinaryMode(stdin);
45464623
setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
45474624
Argv0 = argv[0];
45484625
main_init(&data);
45494626
stdin_is_interactive = isatty(0);
4627
+ stdout_is_console = isatty(1);
45504628
45514629
/* Make sure we have a valid signal handler early, before anything
45524630
** else is done.
45534631
*/
45544632
#ifdef SIGINT
@@ -4583,11 +4661,11 @@
45834661
** mean that nothing is read from stdin */
45844662
readStdin = 0;
45854663
nCmd++;
45864664
azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
45874665
if( azCmd==0 ){
4588
- fprintf(stderr, "out of memory\n");
4666
+ raw_printf(stderr, "out of memory\n");
45894667
exit(1);
45904668
}
45914669
azCmd[nCmd-1] = z;
45924670
}
45934671
}
@@ -4665,21 +4743,21 @@
46654743
}else if( strcmp(z,"-vfs")==0 ){
46664744
sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i));
46674745
if( pVfs ){
46684746
sqlite3_vfs_register(pVfs, 1);
46694747
}else{
4670
- fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]);
4748
+ utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
46714749
exit(1);
46724750
}
46734751
}
46744752
}
46754753
if( data.zDbFilename==0 ){
46764754
#ifndef SQLITE_OMIT_MEMORYDB
46774755
data.zDbFilename = ":memory:";
46784756
warnInmemoryDb = argc==1;
46794757
#else
4680
- fprintf(stderr,"%s: Error: no database filename specified\n", Argv0);
4758
+ utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
46814759
return 1;
46824760
#endif
46834761
}
46844762
data.out = stdout;
46854763
@@ -4797,20 +4875,20 @@
47974875
if( rc && bail_on_error ) return rc==2 ? 0 : rc;
47984876
}else{
47994877
open_db(&data, 0);
48004878
rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg);
48014879
if( zErrMsg!=0 ){
4802
- fprintf(stderr,"Error: %s\n", zErrMsg);
4880
+ utf8_printf(stderr,"Error: %s\n", zErrMsg);
48034881
if( bail_on_error ) return rc!=0 ? rc : 1;
48044882
}else if( rc!=0 ){
4805
- fprintf(stderr,"Error: unable to process SQL \"%s\"\n", z);
4883
+ utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
48064884
if( bail_on_error ) return rc;
48074885
}
48084886
}
48094887
}else{
4810
- fprintf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
4811
- fprintf(stderr,"Use -help for a list of options.\n");
4888
+ utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
4889
+ raw_printf(stderr,"Use -help for a list of options.\n");
48124890
return 1;
48134891
}
48144892
}
48154893
48164894
if( !readStdin ){
@@ -4824,14 +4902,14 @@
48244902
if( rc ) return rc==2 ? 0 : rc;
48254903
}else{
48264904
open_db(&data, 0);
48274905
rc = shell_exec(data.db, azCmd[i], shell_callback, &data, &zErrMsg);
48284906
if( zErrMsg!=0 ){
4829
- fprintf(stderr,"Error: %s\n", zErrMsg);
4907
+ utf8_printf(stderr,"Error: %s\n", zErrMsg);
48304908
return rc!=0 ? rc : 1;
48314909
}else if( rc!=0 ){
4832
- fprintf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
4910
+ utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
48334911
return rc;
48344912
}
48354913
}
48364914
}
48374915
free(azCmd);
48384916
--- src/shell.c
+++ src/shell.c
@@ -327,10 +327,17 @@
327 ** Threat stdin as an interactive input if the following variable
328 ** is true. Otherwise, assume stdin is connected to a file or pipe.
329 */
330 static int stdin_is_interactive = 1;
331
 
 
 
 
 
 
 
332 /*
333 ** The following is the open SQLite database. We make a pointer
334 ** to this database a static variable so that it can be accessed
335 ** by the SIGINT handler to interrupt database processing.
336 */
@@ -427,10 +434,20 @@
427 UNUSED_PARAMETER(argc);
428 UNUSED_PARAMETER(argv);
429 sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC);
430 }
431
 
 
 
 
 
 
 
 
 
 
432
433 /*
434 ** This routine reads a line of text from FILE in, stores
435 ** the text in memory obtained from malloc() and returns a pointer
436 ** to the text. NULL is returned at end of file, or if malloc()
@@ -463,10 +480,30 @@
463 if( n>0 && zLine[n-1]=='\r' ) n--;
464 zLine[n] = 0;
465 break;
466 }
467 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
468 return zLine;
469 }
470
471 /*
472 ** Retrieve a single line of input text.
@@ -500,10 +537,43 @@
500 #endif
501 }
502 return zResult;
503 }
504
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505 /*
506 ** Shell output mode information from before ".explain on",
507 ** saved so that it can be restored by ".explain off"
508 */
509 typedef struct SavedModeInfo SavedModeInfo;
@@ -605,39 +675,29 @@
605 /*
606 ** Number of elements in an array
607 */
608 #define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
609
610 /*
611 ** Compute a string length that is limited to what can be stored in
612 ** lower 30 bits of a 32-bit signed integer.
613 */
614 static int strlen30(const char *z){
615 const char *z2 = z;
616 while( *z2 ){ z2++; }
617 return 0x3fffffff & (int)(z2 - z);
618 }
619
620 /*
621 ** A callback for the sqlite3_log() interface.
622 */
623 static void shellLog(void *pArg, int iErrCode, const char *zMsg){
624 ShellState *p = (ShellState*)pArg;
625 if( p->pLog==0 ) return;
626 fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
627 fflush(p->pLog);
628 }
629
630 /*
631 ** Output the given string as a hex-encoded blob (eg. X'1234' )
632 */
633 static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
634 int i;
635 char *zBlob = (char *)pBlob;
636 fprintf(out,"X'");
637 for(i=0; i<nBlob; i++){ fprintf(out,"%02x",zBlob[i]&0xff); }
638 fprintf(out,"'");
639 }
640
641 /*
642 ** Output the given string as a quoted string using SQL quoting conventions.
643 */
@@ -647,27 +707,27 @@
647 setBinaryMode(out);
648 for(i=0; z[i]; i++){
649 if( z[i]=='\'' ) nSingle++;
650 }
651 if( nSingle==0 ){
652 fprintf(out,"'%s'",z);
653 }else{
654 fprintf(out,"'");
655 while( *z ){
656 for(i=0; z[i] && z[i]!='\''; i++){}
657 if( i==0 ){
658 fprintf(out,"''");
659 z++;
660 }else if( z[i]=='\'' ){
661 fprintf(out,"%.*s''",i,z);
662 z += i+1;
663 }else{
664 fprintf(out,"%s",z);
665 break;
666 }
667 }
668 fprintf(out,"'");
669 }
670 setTextMode(out);
671 }
672
673 /*
@@ -691,11 +751,11 @@
691 fputc('n', out);
692 }else if( c=='\r' ){
693 fputc('\\', out);
694 fputc('r', out);
695 }else if( !isprint(c&0xff) ){
696 fprintf(out, "\\%03o", c&0xff);
697 }else{
698 fputc(c, out);
699 }
700 }
701 fputc('"', out);
@@ -715,22 +775,22 @@
715 && z[i]!='>'
716 && z[i]!='\"'
717 && z[i]!='\'';
718 i++){}
719 if( i>0 ){
720 fprintf(out,"%.*s",i,z);
721 }
722 if( z[i]=='<' ){
723 fprintf(out,"&lt;");
724 }else if( z[i]=='&' ){
725 fprintf(out,"&amp;");
726 }else if( z[i]=='>' ){
727 fprintf(out,"&gt;");
728 }else if( z[i]=='\"' ){
729 fprintf(out,"&quot;");
730 }else if( z[i]=='\'' ){
731 fprintf(out,"&#39;");
732 }else{
733 break;
734 }
735 z += i + 1;
736 }
@@ -766,11 +826,11 @@
766 ** is only issued if bSep is true.
767 */
768 static void output_csv(ShellState *p, const char *z, int bSep){
769 FILE *out = p->out;
770 if( z==0 ){
771 fprintf(out,"%s",p->nullValue);
772 }else{
773 int i;
774 int nSep = strlen30(p->colSeparator);
775 for(i=0; z[i]; i++){
776 if( needCsvQuote[((unsigned char*)z)[i]]
@@ -786,15 +846,15 @@
786 if( z[i]=='"' ) putc('"', out);
787 putc(z[i], out);
788 }
789 putc('"', out);
790 }else{
791 fprintf(out, "%s", z);
792 }
793 }
794 if( bSep ){
795 fprintf(p->out, "%s", p->colSeparator);
796 }
797 }
798
799 #ifdef SIGINT
800 /*
@@ -828,13 +888,13 @@
828 if( azArg==0 ) break;
829 for(i=0; i<nArg; i++){
830 int len = strlen30(azCol[i] ? azCol[i] : "");
831 if( len>w ) w = len;
832 }
833 if( p->cnt++>0 ) fprintf(p->out, "%s", p->rowSeparator);
834 for(i=0; i<nArg; i++){
835 fprintf(p->out,"%*s = %s%s", w, azCol[i],
836 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
837 }
838 break;
839 }
840 case MODE_Explain:
@@ -856,14 +916,14 @@
856 if( i<ArraySize(p->actualWidth) ){
857 p->actualWidth[i] = w;
858 }
859 if( p->showHeader ){
860 if( w<0 ){
861 fprintf(p->out,"%*.*s%s",-w,-w,azCol[i],
862 i==nArg-1 ? p->rowSeparator : " ");
863 }else{
864 fprintf(p->out,"%-*.*s%s",w,w,azCol[i],
865 i==nArg-1 ? p->rowSeparator : " ");
866 }
867 }
868 }
869 if( p->showHeader ){
@@ -873,11 +933,12 @@
873 w = p->actualWidth[i];
874 if( w<0 ) w = -w;
875 }else{
876 w = 10;
877 }
878 fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------"
 
879 "----------------------------------------------------------",
880 i==nArg-1 ? p->rowSeparator : " ");
881 }
882 }
883 }
@@ -892,20 +953,20 @@
892 if( p->mode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){
893 w = strlen30(azArg[i]);
894 }
895 if( i==1 && p->aiIndent && p->pStmt ){
896 if( p->iIndent<p->nIndent ){
897 fprintf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
898 }
899 p->iIndent++;
900 }
901 if( w<0 ){
902 fprintf(p->out,"%*.*s%s",-w,-w,
903 azArg[i] ? azArg[i] : p->nullValue,
904 i==nArg-1 ? p->rowSeparator : " ");
905 }else{
906 fprintf(p->out,"%-*.*s%s",w,w,
907 azArg[i] ? azArg[i] : p->nullValue,
908 i==nArg-1 ? p->rowSeparator : " ");
909 }
910 }
911 break;
@@ -912,134 +973,134 @@
912 }
913 case MODE_Semi:
914 case MODE_List: {
915 if( p->cnt++==0 && p->showHeader ){
916 for(i=0; i<nArg; i++){
917 fprintf(p->out,"%s%s",azCol[i],
918 i==nArg-1 ? p->rowSeparator : p->colSeparator);
919 }
920 }
921 if( azArg==0 ) break;
922 for(i=0; i<nArg; i++){
923 char *z = azArg[i];
924 if( z==0 ) z = p->nullValue;
925 fprintf(p->out, "%s", z);
926 if( i<nArg-1 ){
927 fprintf(p->out, "%s", p->colSeparator);
928 }else if( p->mode==MODE_Semi ){
929 fprintf(p->out, ";%s", p->rowSeparator);
930 }else{
931 fprintf(p->out, "%s", p->rowSeparator);
932 }
933 }
934 break;
935 }
936 case MODE_Html: {
937 if( p->cnt++==0 && p->showHeader ){
938 fprintf(p->out,"<TR>");
939 for(i=0; i<nArg; i++){
940 fprintf(p->out,"<TH>");
941 output_html_string(p->out, azCol[i]);
942 fprintf(p->out,"</TH>\n");
943 }
944 fprintf(p->out,"</TR>\n");
945 }
946 if( azArg==0 ) break;
947 fprintf(p->out,"<TR>");
948 for(i=0; i<nArg; i++){
949 fprintf(p->out,"<TD>");
950 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
951 fprintf(p->out,"</TD>\n");
952 }
953 fprintf(p->out,"</TR>\n");
954 break;
955 }
956 case MODE_Tcl: {
957 if( p->cnt++==0 && p->showHeader ){
958 for(i=0; i<nArg; i++){
959 output_c_string(p->out,azCol[i] ? azCol[i] : "");
960 if(i<nArg-1) fprintf(p->out, "%s", p->colSeparator);
961 }
962 fprintf(p->out, "%s", p->rowSeparator);
963 }
964 if( azArg==0 ) break;
965 for(i=0; i<nArg; i++){
966 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
967 if(i<nArg-1) fprintf(p->out, "%s", p->colSeparator);
968 }
969 fprintf(p->out, "%s", p->rowSeparator);
970 break;
971 }
972 case MODE_Csv: {
973 setBinaryMode(p->out);
974 if( p->cnt++==0 && p->showHeader ){
975 for(i=0; i<nArg; i++){
976 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
977 }
978 fprintf(p->out, "%s", p->rowSeparator);
979 }
980 if( nArg>0 ){
981 for(i=0; i<nArg; i++){
982 output_csv(p, azArg[i], i<nArg-1);
983 }
984 fprintf(p->out, "%s", p->rowSeparator);
985 }
986 setTextMode(p->out);
987 break;
988 }
989 case MODE_Insert: {
990 p->cnt++;
991 if( azArg==0 ) break;
992 fprintf(p->out,"INSERT INTO %s",p->zDestTable);
993 if( p->showHeader ){
994 fprintf(p->out,"(");
995 for(i=0; i<nArg; i++){
996 char *zSep = i>0 ? ",": "";
997 fprintf(p->out, "%s%s", zSep, azCol[i]);
998 }
999 fprintf(p->out,")");
1000 }
1001 fprintf(p->out," VALUES(");
1002 for(i=0; i<nArg; i++){
1003 char *zSep = i>0 ? ",": "";
1004 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
1005 fprintf(p->out,"%sNULL",zSep);
1006 }else if( aiType && aiType[i]==SQLITE_TEXT ){
1007 if( zSep[0] ) fprintf(p->out,"%s",zSep);
1008 output_quoted_string(p->out, azArg[i]);
1009 }else if( aiType && (aiType[i]==SQLITE_INTEGER
1010 || aiType[i]==SQLITE_FLOAT) ){
1011 fprintf(p->out,"%s%s",zSep, azArg[i]);
1012 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
1013 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
1014 int nBlob = sqlite3_column_bytes(p->pStmt, i);
1015 if( zSep[0] ) fprintf(p->out,"%s",zSep);
1016 output_hex_blob(p->out, pBlob, nBlob);
1017 }else if( isNumber(azArg[i], 0) ){
1018 fprintf(p->out,"%s%s",zSep, azArg[i]);
1019 }else{
1020 if( zSep[0] ) fprintf(p->out,"%s",zSep);
1021 output_quoted_string(p->out, azArg[i]);
1022 }
1023 }
1024 fprintf(p->out,");\n");
1025 break;
1026 }
1027 case MODE_Ascii: {
1028 if( p->cnt++==0 && p->showHeader ){
1029 for(i=0; i<nArg; i++){
1030 if( i>0 ) fprintf(p->out, "%s", p->colSeparator);
1031 fprintf(p->out,"%s",azCol[i] ? azCol[i] : "");
1032 }
1033 fprintf(p->out, "%s", p->rowSeparator);
1034 }
1035 if( azArg==0 ) break;
1036 for(i=0; i<nArg; i++){
1037 if( i>0 ) fprintf(p->out, "%s", p->colSeparator);
1038 fprintf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
1039 }
1040 fprintf(p->out, "%s", p->rowSeparator);
1041 break;
1042 }
1043 }
1044 return 0;
1045 }
@@ -1076,11 +1137,11 @@
1076 }
1077 }
1078 if( needQuote ) n += 2;
1079 z = p->zDestTable = malloc( n+1 );
1080 if( z==0 ){
1081 fprintf(stderr,"Error: out of memory\n");
1082 exit(1);
1083 }
1084 n = 0;
1085 if( needQuote ) z[n++] = '\'';
1086 for(i=0; zName[i]; i++){
@@ -1157,38 +1218,40 @@
1157 int nResult;
1158 int i;
1159 const char *z;
1160 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
1161 if( rc!=SQLITE_OK || !pSelect ){
1162 fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
 
1163 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
1164 return rc;
1165 }
1166 rc = sqlite3_step(pSelect);
1167 nResult = sqlite3_column_count(pSelect);
1168 while( rc==SQLITE_ROW ){
1169 if( zFirstRow ){
1170 fprintf(p->out, "%s", zFirstRow);
1171 zFirstRow = 0;
1172 }
1173 z = (const char*)sqlite3_column_text(pSelect, 0);
1174 fprintf(p->out, "%s", z);
1175 for(i=1; i<nResult; i++){
1176 fprintf(p->out, ",%s", sqlite3_column_text(pSelect, i));
1177 }
1178 if( z==0 ) z = "";
1179 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
1180 if( z[0] ){
1181 fprintf(p->out, "\n;\n");
1182 }else{
1183 fprintf(p->out, ";\n");
1184 }
1185 rc = sqlite3_step(pSelect);
1186 }
1187 rc = sqlite3_finalize(pSelect);
1188 if( rc!=SQLITE_OK ){
1189 fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
 
1190 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
1191 }
1192 return rc;
1193 }
1194
@@ -1219,107 +1282,115 @@
1219
1220 if( pArg && pArg->out ){
1221
1222 iHiwtr = iCur = -1;
1223 sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset);
1224 fprintf(pArg->out,
1225 "Memory Used: %d (max %d) bytes\n",
1226 iCur, iHiwtr);
1227 iHiwtr = iCur = -1;
1228 sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset);
1229 fprintf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n",
1230 iCur, iHiwtr);
1231 if( pArg->shellFlgs & SHFLG_Pagecache ){
1232 iHiwtr = iCur = -1;
1233 sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset);
1234 fprintf(pArg->out,
1235 "Number of Pcache Pages Used: %d (max %d) pages\n",
1236 iCur, iHiwtr);
1237 }
1238 iHiwtr = iCur = -1;
1239 sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset);
1240 fprintf(pArg->out,
1241 "Number of Pcache Overflow Bytes: %d (max %d) bytes\n",
1242 iCur, iHiwtr);
1243 if( pArg->shellFlgs & SHFLG_Scratch ){
1244 iHiwtr = iCur = -1;
1245 sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset);
1246 fprintf(pArg->out, "Number of Scratch Allocations Used: %d (max %d)\n",
 
1247 iCur, iHiwtr);
1248 }
1249 iHiwtr = iCur = -1;
1250 sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset);
1251 fprintf(pArg->out,
1252 "Number of Scratch Overflow Bytes: %d (max %d) bytes\n",
1253 iCur, iHiwtr);
1254 iHiwtr = iCur = -1;
1255 sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset);
1256 fprintf(pArg->out, "Largest Allocation: %d bytes\n",
1257 iHiwtr);
1258 iHiwtr = iCur = -1;
1259 sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset);
1260 fprintf(pArg->out, "Largest Pcache Allocation: %d bytes\n",
1261 iHiwtr);
1262 iHiwtr = iCur = -1;
1263 sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset);
1264 fprintf(pArg->out, "Largest Scratch Allocation: %d bytes\n",
1265 iHiwtr);
1266 #ifdef YYTRACKMAXSTACKDEPTH
1267 iHiwtr = iCur = -1;
1268 sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset);
1269 fprintf(pArg->out, "Deepest Parser Stack: %d (max %d)\n",
1270 iCur, iHiwtr);
1271 #endif
1272 }
1273
1274 if( pArg && pArg->out && db ){
1275 if( pArg->shellFlgs & SHFLG_Lookaside ){
1276 iHiwtr = iCur = -1;
1277 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
1278 &iCur, &iHiwtr, bReset);
1279 fprintf(pArg->out, "Lookaside Slots Used: %d (max %d)\n",
 
1280 iCur, iHiwtr);
1281 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
1282 &iCur, &iHiwtr, bReset);
1283 fprintf(pArg->out, "Successful lookaside attempts: %d\n", iHiwtr);
 
1284 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
1285 &iCur, &iHiwtr, bReset);
1286 fprintf(pArg->out, "Lookaside failures due to size: %d\n", iHiwtr);
 
1287 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
1288 &iCur, &iHiwtr, bReset);
1289 fprintf(pArg->out, "Lookaside failures due to OOM: %d\n", iHiwtr);
 
1290 }
1291 iHiwtr = iCur = -1;
1292 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
1293 fprintf(pArg->out, "Pager Heap Usage: %d bytes\n",iCur);
 
1294 iHiwtr = iCur = -1;
1295 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
1296 fprintf(pArg->out, "Page cache hits: %d\n", iCur);
1297 iHiwtr = iCur = -1;
1298 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
1299 fprintf(pArg->out, "Page cache misses: %d\n", iCur);
1300 iHiwtr = iCur = -1;
1301 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
1302 fprintf(pArg->out, "Page cache writes: %d\n", iCur);
1303 iHiwtr = iCur = -1;
1304 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
1305 fprintf(pArg->out, "Schema Heap Usage: %d bytes\n",iCur);
 
1306 iHiwtr = iCur = -1;
1307 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
1308 fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",iCur);
 
1309 }
1310
1311 if( pArg && pArg->out && db && pArg->pStmt ){
1312 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
1313 bReset);
1314 fprintf(pArg->out, "Fullscan Steps: %d\n", iCur);
1315 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
1316 fprintf(pArg->out, "Sort Operations: %d\n", iCur);
1317 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
1318 fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur);
1319 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
1320 fprintf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
1321 }
1322
1323 /* Do not remove this machine readable comment: extra-stats-output-here */
1324
1325 return 0;
@@ -1335,11 +1406,11 @@
1335 #ifndef SQLITE_ENABLE_STMT_SCANSTATUS
1336 UNUSED_PARAMETER(db);
1337 UNUSED_PARAMETER(pArg);
1338 #else
1339 int i, k, n, mx;
1340 fprintf(pArg->out, "-------- scanstats --------\n");
1341 mx = 0;
1342 for(k=0; k<=mx; k++){
1343 double rEstLoop = 1.0;
1344 for(i=n=0; 1; i++){
1345 sqlite3_stmt *p = pArg->pStmt;
@@ -1353,25 +1424,25 @@
1353 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
1354 if( iSid>mx ) mx = iSid;
1355 if( iSid!=k ) continue;
1356 if( n==0 ){
1357 rEstLoop = (double)nLoop;
1358 if( k>0 ) fprintf(pArg->out, "-------- subquery %d -------\n", k);
1359 }
1360 n++;
1361 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
1362 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
1363 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
1364 fprintf(pArg->out, "Loop %2d: %s\n", n, zExplain);
1365 rEstLoop *= rEst;
1366 fprintf(pArg->out,
1367 " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
1368 nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
1369 );
1370 }
1371 }
1372 fprintf(pArg->out, "---------------------------\n");
1373 #endif
1374 }
1375
1376 /*
1377 ** Parameter azArray points to a zero-terminated array of strings. zStr
@@ -1520,11 +1591,11 @@
1520 }
1521
1522 /* echo the sql statement if echo on */
1523 if( pArg && pArg->echoOn ){
1524 const char *zStmtSql = sqlite3_sql(pStmt);
1525 fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
1526 }
1527
1528 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
1529 if( pArg && pArg->autoEQP ){
1530 sqlite3_stmt *pExplain;
@@ -1531,14 +1602,14 @@
1531 char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s",
1532 sqlite3_sql(pStmt));
1533 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
1534 if( rc==SQLITE_OK ){
1535 while( sqlite3_step(pExplain)==SQLITE_ROW ){
1536 fprintf(pArg->out,"--EQP-- %d,", sqlite3_column_int(pExplain, 0));
1537 fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1));
1538 fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2));
1539 fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
1540 }
1541 }
1542 sqlite3_finalize(pExplain);
1543 sqlite3_free(zEQP);
1544 }
@@ -1662,28 +1733,28 @@
1662 zSql = azArg[2];
1663
1664 if( strcmp(zTable, "sqlite_sequence")==0 ){
1665 zPrepStmt = "DELETE FROM sqlite_sequence;\n";
1666 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
1667 fprintf(p->out, "ANALYZE sqlite_master;\n");
1668 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
1669 return 0;
1670 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
1671 char *zIns;
1672 if( !p->writableSchema ){
1673 fprintf(p->out, "PRAGMA writable_schema=ON;\n");
1674 p->writableSchema = 1;
1675 }
1676 zIns = sqlite3_mprintf(
1677 "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
1678 "VALUES('table','%q','%q',0,'%q');",
1679 zTable, zTable, zSql);
1680 fprintf(p->out, "%s\n", zIns);
1681 sqlite3_free(zIns);
1682 return 0;
1683 }else{
1684 fprintf(p->out, "%s;\n", zSql);
1685 }
1686
1687 if( strcmp(zType, "table")==0 ){
1688 sqlite3_stmt *pTableInfo = 0;
1689 char *zSelect = 0;
@@ -1756,22 +1827,22 @@
1756 char *zErr = 0;
1757 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
1758 if( rc==SQLITE_CORRUPT ){
1759 char *zQ2;
1760 int len = strlen30(zQuery);
1761 fprintf(p->out, "/****** CORRUPTION ERROR *******/\n");
1762 if( zErr ){
1763 fprintf(p->out, "/****** %s ******/\n", zErr);
1764 sqlite3_free(zErr);
1765 zErr = 0;
1766 }
1767 zQ2 = malloc( len+100 );
1768 if( zQ2==0 ) return rc;
1769 sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
1770 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
1771 if( rc ){
1772 fprintf(p->out, "/****** ERROR: %s ******/\n", zErr);
1773 }else{
1774 rc = SQLITE_CORRUPT;
1775 }
1776 sqlite3_free(zErr);
1777 free(zQ2);
@@ -1932,11 +2003,11 @@
1932 if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){
1933 sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0,
1934 shellstaticFunc, 0, 0);
1935 }
1936 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
1937 fprintf(stderr,"Error: unable to open database \"%s\": %s\n",
1938 p->zDbFilename, sqlite3_errmsg(p->db));
1939 if( keepAlive ) return;
1940 exit(1);
1941 }
1942 #ifndef SQLITE_OMIT_LOAD_EXTENSION
@@ -2082,11 +2153,11 @@
2082 return 1;
2083 }
2084 if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
2085 return 0;
2086 }
2087 fprintf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
2088 zArg);
2089 return 0;
2090 }
2091
2092 /*
@@ -2110,11 +2181,11 @@
2110 }else if( strcmp(zFile, "off")==0 ){
2111 f = 0;
2112 }else{
2113 f = fopen(zFile, "wb");
2114 if( f==0 ){
2115 fprintf(stderr, "Error: cannot open \"%s\"\n", zFile);
2116 }
2117 }
2118 return f;
2119 }
2120
@@ -2124,11 +2195,11 @@
2124 static void sql_trace_callback(void *pArg, const char *z){
2125 FILE *f = (FILE*)pArg;
2126 if( f ){
2127 int i = (int)strlen(z);
2128 while( i>0 && z[i-1]==';' ){ i--; }
2129 fprintf(f, "%.*s;\n", i, z);
2130 }
2131 }
2132
2133 /*
2134 ** A no-op routine that runs with the ".breakpoint" doc-command. This is
@@ -2159,11 +2230,11 @@
2159 static void import_append_char(ImportCtx *p, int c){
2160 if( p->n+1>=p->nAlloc ){
2161 p->nAlloc += p->nAlloc + 100;
2162 p->z = sqlite3_realloc64(p->z, p->nAlloc);
2163 if( p->z==0 ){
2164 fprintf(stderr, "out of memory\n");
2165 exit(1);
2166 }
2167 }
2168 p->z[p->n++] = (char)c;
2169 }
@@ -2213,15 +2284,15 @@
2213 do{ p->n--; }while( p->z[p->n]!=cQuote );
2214 p->cTerm = c;
2215 break;
2216 }
2217 if( pc==cQuote && c!='\r' ){
2218 fprintf(stderr, "%s:%d: unescaped %c character\n",
2219 p->zFile, p->nLine, cQuote);
2220 }
2221 if( c==EOF ){
2222 fprintf(stderr, "%s:%d: unterminated %c-quoted field\n",
2223 p->zFile, startLine, cQuote);
2224 p->cTerm = c;
2225 break;
2226 }
2227 import_append_char(p, c);
@@ -2299,19 +2370,19 @@
2299 const int spinRate = 10000;
2300
2301 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
2302 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
2303 if( rc ){
2304 fprintf(stderr, "Error %d: %s on [%s]\n",
2305 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
2306 zQuery);
2307 goto end_data_xfer;
2308 }
2309 n = sqlite3_column_count(pQuery);
2310 zInsert = sqlite3_malloc64(200 + nTable + n*3);
2311 if( zInsert==0 ){
2312 fprintf(stderr, "out of memory\n");
2313 goto end_data_xfer;
2314 }
2315 sqlite3_snprintf(200+nTable,zInsert,
2316 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
2317 i = (int)strlen(zInsert);
@@ -2320,11 +2391,11 @@
2320 i += 2;
2321 }
2322 memcpy(zInsert+i, ");", 3);
2323 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
2324 if( rc ){
2325 fprintf(stderr, "Error %d: %s on [%s]\n",
2326 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
2327 zQuery);
2328 goto end_data_xfer;
2329 }
2330 for(k=0; k<2; k++){
@@ -2357,11 +2428,11 @@
2357 }
2358 }
2359 } /* End for */
2360 rc = sqlite3_step(pInsert);
2361 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
2362 fprintf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
2363 sqlite3_errmsg(newDb));
2364 }
2365 sqlite3_reset(pInsert);
2366 cnt++;
2367 if( (cnt%spinRate)==0 ){
@@ -2374,11 +2445,11 @@
2374 sqlite3_free(zQuery);
2375 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
2376 zTable);
2377 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
2378 if( rc ){
2379 fprintf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
2380 break;
2381 }
2382 } /* End for(k=0...) */
2383
2384 end_data_xfer:
@@ -2410,11 +2481,11 @@
2410
2411 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
2412 " WHERE %s", zWhere);
2413 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
2414 if( rc ){
2415 fprintf(stderr, "Error: (%d) %s on [%s]\n",
2416 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
2417 zQuery);
2418 goto end_schema_xfer;
2419 }
2420 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
@@ -2421,11 +2492,11 @@
2421 zName = sqlite3_column_text(pQuery, 0);
2422 zSql = sqlite3_column_text(pQuery, 1);
2423 printf("%s... ", zName); fflush(stdout);
2424 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
2425 if( zErrMsg ){
2426 fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
2427 sqlite3_free(zErrMsg);
2428 zErrMsg = 0;
2429 }
2430 if( xForEach ){
2431 xForEach(p, newDb, (const char*)zName);
@@ -2437,11 +2508,11 @@
2437 sqlite3_free(zQuery);
2438 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
2439 " WHERE %s ORDER BY rowid DESC", zWhere);
2440 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
2441 if( rc ){
2442 fprintf(stderr, "Error: (%d) %s on [%s]\n",
2443 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
2444 zQuery);
2445 goto end_schema_xfer;
2446 }
2447 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
@@ -2448,11 +2519,11 @@
2448 zName = sqlite3_column_text(pQuery, 0);
2449 zSql = sqlite3_column_text(pQuery, 1);
2450 printf("%s... ", zName); fflush(stdout);
2451 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
2452 if( zErrMsg ){
2453 fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
2454 sqlite3_free(zErrMsg);
2455 zErrMsg = 0;
2456 }
2457 if( xForEach ){
2458 xForEach(p, newDb, (const char*)zName);
@@ -2472,16 +2543,16 @@
2472 */
2473 static void tryToClone(ShellState *p, const char *zNewDb){
2474 int rc;
2475 sqlite3 *newDb = 0;
2476 if( access(zNewDb,0)==0 ){
2477 fprintf(stderr, "File \"%s\" already exists.\n", zNewDb);
2478 return;
2479 }
2480 rc = sqlite3_open(zNewDb, &newDb);
2481 if( rc ){
2482 fprintf(stderr, "Cannot create output database: %s\n",
2483 sqlite3_errmsg(newDb));
2484 }else{
2485 sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
2486 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
2487 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
@@ -2574,31 +2645,31 @@
2574 if( pFile==0 || pFile->pMethods==0 || pFile->pMethods->xRead==0 ){
2575 return 1;
2576 }
2577 i = pFile->pMethods->xRead(pFile, aHdr, 100, 0);
2578 if( i!=SQLITE_OK ){
2579 fprintf(stderr, "unable to read database header\n");
2580 return 1;
2581 }
2582 i = get2byteInt(aHdr+16);
2583 if( i==1 ) i = 65536;
2584 fprintf(p->out, "%-20s %d\n", "database page size:", i);
2585 fprintf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
2586 fprintf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
2587 fprintf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
2588 for(i=0; i<ArraySize(aField); i++){
2589 int ofst = aField[i].ofst;
2590 unsigned int val = get4byteInt(aHdr + ofst);
2591 fprintf(p->out, "%-20s %u", aField[i].zName, val);
2592 switch( ofst ){
2593 case 56: {
2594 if( val==1 ) fprintf(p->out, " (utf8)");
2595 if( val==2 ) fprintf(p->out, " (utf16le)");
2596 if( val==3 ) fprintf(p->out, " (utf16be)");
2597 }
2598 }
2599 fprintf(p->out, "\n");
2600 }
2601 if( zDb==0 ){
2602 zSchemaTab = sqlite3_mprintf("main.sqlite_master");
2603 }else if( strcmp(zDb,"temp")==0 ){
2604 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master");
@@ -2607,11 +2678,11 @@
2607 }
2608 for(i=0; i<ArraySize(aQuery); i++){
2609 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
2610 int val = db_int(p, zSql);
2611 sqlite3_free(zSql);
2612 fprintf(p->out, "%-20s %d\n", aQuery[i].zName, val);
2613 }
2614 sqlite3_free(zSchemaTab);
2615 return 0;
2616 }
2617
@@ -2618,19 +2689,19 @@
2618 /*
2619 ** Print the current sqlite3_errmsg() value to stderr and return 1.
2620 */
2621 static int shellDatabaseError(sqlite3 *db){
2622 const char *zErr = sqlite3_errmsg(db);
2623 fprintf(stderr, "Error: %s\n", zErr);
2624 return 1;
2625 }
2626
2627 /*
2628 ** Print an out-of-memory message to stderr and return 1.
2629 */
2630 static int shellNomemError(void){
2631 fprintf(stderr, "Error: out of memory\n");
2632 return 1;
2633 }
2634
2635 /*
2636 ** If an input line begins with "." then invoke this routine to
@@ -2686,57 +2757,57 @@
2686 const char *z = azArg[j];
2687 if( z[0]=='-' ){
2688 while( z[0]=='-' ) z++;
2689 /* No options to process at this time */
2690 {
2691 fprintf(stderr, "unknown option: %s\n", azArg[j]);
2692 return 1;
2693 }
2694 }else if( zDestFile==0 ){
2695 zDestFile = azArg[j];
2696 }else if( zDb==0 ){
2697 zDb = zDestFile;
2698 zDestFile = azArg[j];
2699 }else{
2700 fprintf(stderr, "too many arguments to .backup\n");
2701 return 1;
2702 }
2703 }
2704 if( zDestFile==0 ){
2705 fprintf(stderr, "missing FILENAME argument on .backup\n");
2706 return 1;
2707 }
2708 if( zDb==0 ) zDb = "main";
2709 rc = sqlite3_open(zDestFile, &pDest);
2710 if( rc!=SQLITE_OK ){
2711 fprintf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
2712 sqlite3_close(pDest);
2713 return 1;
2714 }
2715 open_db(p, 0);
2716 pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
2717 if( pBackup==0 ){
2718 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
2719 sqlite3_close(pDest);
2720 return 1;
2721 }
2722 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
2723 sqlite3_backup_finish(pBackup);
2724 if( rc==SQLITE_DONE ){
2725 rc = 0;
2726 }else{
2727 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
2728 rc = 1;
2729 }
2730 sqlite3_close(pDest);
2731 }else
2732
2733 if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
2734 if( nArg==2 ){
2735 bail_on_error = booleanValue(azArg[1]);
2736 }else{
2737 fprintf(stderr, "Usage: .bail on|off\n");
2738 rc = 1;
2739 }
2740 }else
2741
2742 if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
@@ -2745,11 +2816,11 @@
2745 setBinaryMode(p->out);
2746 }else{
2747 setTextMode(p->out);
2748 }
2749 }else{
2750 fprintf(stderr, "Usage: .binary on|off\n");
2751 rc = 1;
2752 }
2753 }else
2754
2755 /* The undocumented ".breakpoint" command causes a call to the no-op
@@ -2761,20 +2832,20 @@
2761
2762 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
2763 if( nArg==2 ){
2764 p->countChanges = booleanValue(azArg[1]);
2765 }else{
2766 fprintf(stderr, "Usage: .changes on|off\n");
2767 rc = 1;
2768 }
2769 }else
2770
2771 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
2772 if( nArg==2 ){
2773 tryToClone(p, azArg[1]);
2774 }else{
2775 fprintf(stderr, "Usage: .clone FILENAME\n");
2776 rc = 1;
2777 }
2778 }else
2779
2780 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
@@ -2788,11 +2859,11 @@
2788 data.colWidth[1] = 15;
2789 data.colWidth[2] = 58;
2790 data.cnt = 0;
2791 sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
2792 if( zErrMsg ){
2793 fprintf(stderr,"Error: %s\n", zErrMsg);
2794 sqlite3_free(zErrMsg);
2795 rc = 1;
2796 }
2797 }else
2798
@@ -2804,16 +2875,16 @@
2804 open_db(p, 0);
2805 /* When playing back a "dump", the content might appear in an order
2806 ** which causes immediate foreign key constraints to be violated.
2807 ** So disable foreign-key constraint enforcement to prevent problems. */
2808 if( nArg!=1 && nArg!=2 ){
2809 fprintf(stderr, "Usage: .dump ?LIKE-PATTERN?\n");
2810 rc = 1;
2811 goto meta_command_exit;
2812 }
2813 fprintf(p->out, "PRAGMA foreign_keys=OFF;\n");
2814 fprintf(p->out, "BEGIN TRANSACTION;\n");
2815 p->writableSchema = 0;
2816 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
2817 p->nErr = 0;
2818 if( nArg==1 ){
2819 run_schema_dump_query(p,
@@ -2844,32 +2915,32 @@
2844 );
2845 zShellStatic = 0;
2846 }
2847 }
2848 if( p->writableSchema ){
2849 fprintf(p->out, "PRAGMA writable_schema=OFF;\n");
2850 p->writableSchema = 0;
2851 }
2852 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
2853 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
2854 fprintf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
2855 }else
2856
2857 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
2858 if( nArg==2 ){
2859 p->echoOn = booleanValue(azArg[1]);
2860 }else{
2861 fprintf(stderr, "Usage: .echo on|off\n");
2862 rc = 1;
2863 }
2864 }else
2865
2866 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
2867 if( nArg==2 ){
2868 p->autoEQP = booleanValue(azArg[1]);
2869 }else{
2870 fprintf(stderr, "Usage: .eqp on|off\n");
2871 rc = 1;
2872 }
2873 }else
2874
2875 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
@@ -2915,11 +2986,11 @@
2915 if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
2916 ShellState data;
2917 char *zErrMsg = 0;
2918 int doStats = 0;
2919 if( nArg!=1 ){
2920 fprintf(stderr, "Usage: .fullschema\n");
2921 rc = 1;
2922 goto meta_command_exit;
2923 }
2924 open_db(p, 0);
2925 memcpy(&data, p, sizeof(data));
@@ -2942,13 +3013,13 @@
2942 -1, &pStmt, 0);
2943 doStats = sqlite3_step(pStmt)==SQLITE_ROW;
2944 sqlite3_finalize(pStmt);
2945 }
2946 if( doStats==0 ){
2947 fprintf(p->out, "/* No STAT tables available */\n");
2948 }else{
2949 fprintf(p->out, "ANALYZE sqlite_master;\n");
2950 sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'",
2951 callback, &data, &zErrMsg);
2952 data.mode = MODE_Insert;
2953 data.zDestTable = "sqlite_stat1";
2954 shell_exec(p->db, "SELECT * FROM sqlite_stat1",
@@ -2957,25 +3028,25 @@
2957 shell_exec(p->db, "SELECT * FROM sqlite_stat3",
2958 shell_callback, &data,&zErrMsg);
2959 data.zDestTable = "sqlite_stat4";
2960 shell_exec(p->db, "SELECT * FROM sqlite_stat4",
2961 shell_callback, &data, &zErrMsg);
2962 fprintf(p->out, "ANALYZE sqlite_master;\n");
2963 }
2964 }else
2965
2966 if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
2967 if( nArg==2 ){
2968 p->showHeader = booleanValue(azArg[1]);
2969 }else{
2970 fprintf(stderr, "Usage: .headers on|off\n");
2971 rc = 1;
2972 }
2973 }else
2974
2975 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
2976 fprintf(p->out, "%s", zHelp);
2977 }else
2978
2979 if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
2980 char *zTable; /* Insert data into this table */
2981 char *zFile; /* Name of file to extra content from */
@@ -2989,31 +3060,32 @@
2989 ImportCtx sCtx; /* Reader context */
2990 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
2991 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close file */
2992
2993 if( nArg!=3 ){
2994 fprintf(stderr, "Usage: .import FILE TABLE\n");
2995 goto meta_command_exit;
2996 }
2997 zFile = azArg[1];
2998 zTable = azArg[2];
2999 seenInterrupt = 0;
3000 memset(&sCtx, 0, sizeof(sCtx));
3001 open_db(p, 0);
3002 nSep = strlen30(p->colSeparator);
3003 if( nSep==0 ){
3004 fprintf(stderr, "Error: non-null column separator required for import\n");
 
3005 return 1;
3006 }
3007 if( nSep>1 ){
3008 fprintf(stderr, "Error: multi-character column separators not allowed"
3009 " for import\n");
3010 return 1;
3011 }
3012 nSep = strlen30(p->rowSeparator);
3013 if( nSep==0 ){
3014 fprintf(stderr, "Error: non-null row separator required for import\n");
3015 return 1;
3016 }
3017 if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){
3018 /* When importing CSV (only), if the row separator is set to the
3019 ** default output row separator, change it to the default input
@@ -3021,19 +3093,19 @@
3021 ** and output row separators. */
3022 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
3023 nSep = strlen30(p->rowSeparator);
3024 }
3025 if( nSep>1 ){
3026 fprintf(stderr, "Error: multi-character row separators not allowed"
3027 " for import\n");
3028 return 1;
3029 }
3030 sCtx.zFile = zFile;
3031 sCtx.nLine = 1;
3032 if( sCtx.zFile[0]=='|' ){
3033 #ifdef SQLITE_OMIT_POPEN
3034 fprintf(stderr, "Error: pipes are not supported in this OS\n");
3035 return 1;
3036 #else
3037 sCtx.in = popen(sCtx.zFile+1, "r");
3038 sCtx.zFile = "<pipe>";
3039 xCloser = pclose;
@@ -3046,18 +3118,18 @@
3046 xRead = ascii_read_one_field;
3047 }else{
3048 xRead = csv_read_one_field;
3049 }
3050 if( sCtx.in==0 ){
3051 fprintf(stderr, "Error: cannot open \"%s\"\n", zFile);
3052 return 1;
3053 }
3054 sCtx.cColSep = p->colSeparator[0];
3055 sCtx.cRowSep = p->rowSeparator[0];
3056 zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
3057 if( zSql==0 ){
3058 fprintf(stderr, "Error: out of memory\n");
3059 xCloser(sCtx.in);
3060 return 1;
3061 }
3062 nByte = strlen30(zSql);
3063 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
@@ -3072,18 +3144,18 @@
3072 }
3073 if( cSep=='(' ){
3074 sqlite3_free(zCreate);
3075 sqlite3_free(sCtx.z);
3076 xCloser(sCtx.in);
3077 fprintf(stderr,"%s: empty file\n", sCtx.zFile);
3078 return 1;
3079 }
3080 zCreate = sqlite3_mprintf("%z\n)", zCreate);
3081 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
3082 sqlite3_free(zCreate);
3083 if( rc ){
3084 fprintf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
3085 sqlite3_errmsg(p->db));
3086 sqlite3_free(sCtx.z);
3087 xCloser(sCtx.in);
3088 return 1;
3089 }
@@ -3090,21 +3162,21 @@
3090 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3091 }
3092 sqlite3_free(zSql);
3093 if( rc ){
3094 if (pStmt) sqlite3_finalize(pStmt);
3095 fprintf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
3096 xCloser(sCtx.in);
3097 return 1;
3098 }
3099 nCol = sqlite3_column_count(pStmt);
3100 sqlite3_finalize(pStmt);
3101 pStmt = 0;
3102 if( nCol==0 ) return 0; /* no columns, no error */
3103 zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
3104 if( zSql==0 ){
3105 fprintf(stderr, "Error: out of memory\n");
3106 xCloser(sCtx.in);
3107 return 1;
3108 }
3109 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
3110 j = strlen30(zSql);
@@ -3115,11 +3187,11 @@
3115 zSql[j++] = ')';
3116 zSql[j] = 0;
3117 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3118 sqlite3_free(zSql);
3119 if( rc ){
3120 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
3121 if (pStmt) sqlite3_finalize(pStmt);
3122 xCloser(sCtx.in);
3123 return 1;
3124 }
3125 needCommit = sqlite3_get_autocommit(p->db);
@@ -3139,11 +3211,11 @@
3139 ** the remaining columns.
3140 */
3141 if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
3142 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
3143 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
3144 fprintf(stderr, "%s:%d: expected %d columns but found %d - "
3145 "filling the rest with NULL\n",
3146 sCtx.zFile, startLine, nCol, i+1);
3147 i += 2;
3148 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
3149 }
@@ -3151,20 +3223,20 @@
3151 if( sCtx.cTerm==sCtx.cColSep ){
3152 do{
3153 xRead(&sCtx);
3154 i++;
3155 }while( sCtx.cTerm==sCtx.cColSep );
3156 fprintf(stderr, "%s:%d: expected %d columns but found %d - "
3157 "extras ignored\n",
3158 sCtx.zFile, startLine, nCol, i);
3159 }
3160 if( i>=nCol ){
3161 sqlite3_step(pStmt);
3162 rc = sqlite3_reset(pStmt);
3163 if( rc!=SQLITE_OK ){
3164 fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile, startLine,
3165 sqlite3_errmsg(p->db));
3166 }
3167 }
3168 }while( sCtx.cTerm!=EOF );
3169
3170 xCloser(sCtx.in);
@@ -3202,20 +3274,21 @@
3202 "ORDER BY 1",
3203 callback, &data, &zErrMsg
3204 );
3205 zShellStatic = 0;
3206 }else{
3207 fprintf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
3208 rc = 1;
3209 goto meta_command_exit;
3210 }
3211 if( zErrMsg ){
3212 fprintf(stderr,"Error: %s\n", zErrMsg);
3213 sqlite3_free(zErrMsg);
3214 rc = 1;
3215 }else if( rc != SQLITE_OK ){
3216 fprintf(stderr,"Error: querying sqlite_master and sqlite_temp_master\n");
 
3217 rc = 1;
3218 }
3219 }else
3220
3221 #ifdef SQLITE_ENABLE_IOTRACE
@@ -3229,11 +3302,11 @@
3229 sqlite3IoTrace = iotracePrintf;
3230 iotrace = stdout;
3231 }else{
3232 iotrace = fopen(azArg[1], "w");
3233 if( iotrace==0 ){
3234 fprintf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
3235 sqlite3IoTrace = 0;
3236 rc = 1;
3237 }else{
3238 sqlite3IoTrace = iotracePrintf;
3239 }
@@ -3264,11 +3337,11 @@
3264 for(i=0; i<ArraySize(aLimit); i++){
3265 printf("%20s %d\n", aLimit[i].zLimitName,
3266 sqlite3_limit(p->db, aLimit[i].limitCode, -1));
3267 }
3268 }else if( nArg>3 ){
3269 fprintf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
3270 rc = 1;
3271 goto meta_command_exit;
3272 }else{
3273 int iLimit = -1;
3274 n2 = strlen30(azArg[1]);
@@ -3275,18 +3348,18 @@
3275 for(i=0; i<ArraySize(aLimit); i++){
3276 if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
3277 if( iLimit<0 ){
3278 iLimit = i;
3279 }else{
3280 fprintf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
3281 rc = 1;
3282 goto meta_command_exit;
3283 }
3284 }
3285 }
3286 if( iLimit<0 ){
3287 fprintf(stderr, "unknown limit: \"%s\"\n"
3288 "enter \".limits\" with no arguments for a list.\n",
3289 azArg[1]);
3290 rc = 1;
3291 goto meta_command_exit;
3292 }
@@ -3302,29 +3375,29 @@
3302 #ifndef SQLITE_OMIT_LOAD_EXTENSION
3303 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
3304 const char *zFile, *zProc;
3305 char *zErrMsg = 0;
3306 if( nArg<2 ){
3307 fprintf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
3308 rc = 1;
3309 goto meta_command_exit;
3310 }
3311 zFile = azArg[1];
3312 zProc = nArg>=3 ? azArg[2] : 0;
3313 open_db(p, 0);
3314 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
3315 if( rc!=SQLITE_OK ){
3316 fprintf(stderr, "Error: %s\n", zErrMsg);
3317 sqlite3_free(zErrMsg);
3318 rc = 1;
3319 }
3320 }else
3321 #endif
3322
3323 if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
3324 if( nArg!=2 ){
3325 fprintf(stderr, "Usage: .log FILENAME\n");
3326 rc = 1;
3327 }else{
3328 const char *zFile = azArg[1];
3329 output_file_close(p->pLog);
3330 p->pLog = output_file_open(zFile);
@@ -3359,11 +3432,11 @@
3359 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
3360 p->mode = MODE_Ascii;
3361 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
3362 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
3363 }else {
3364 fprintf(stderr,"Error: mode should be one of: "
3365 "ascii column csv html insert line list tabs tcl\n");
3366 rc = 1;
3367 }
3368 }else
3369
@@ -3370,11 +3443,11 @@
3370 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
3371 if( nArg==2 ){
3372 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
3373 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
3374 }else{
3375 fprintf(stderr, "Usage: .nullvalue STRING\n");
3376 rc = 1;
3377 }
3378 }else
3379
3380 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
@@ -3399,17 +3472,17 @@
3399 if( c=='o'
3400 && (strncmp(azArg[0], "output", n)==0 || strncmp(azArg[0], "once", n)==0)
3401 ){
3402 const char *zFile = nArg>=2 ? azArg[1] : "stdout";
3403 if( nArg>2 ){
3404 fprintf(stderr, "Usage: .%s FILE\n", azArg[0]);
3405 rc = 1;
3406 goto meta_command_exit;
3407 }
3408 if( n>1 && strncmp(azArg[0], "once", n)==0 ){
3409 if( nArg<2 ){
3410 fprintf(stderr, "Usage: .once FILE\n");
3411 rc = 1;
3412 goto meta_command_exit;
3413 }
3414 p->outCount = 2;
3415 }else{
@@ -3416,17 +3489,17 @@
3416 p->outCount = 0;
3417 }
3418 output_reset(p);
3419 if( zFile[0]=='|' ){
3420 #ifdef SQLITE_OMIT_POPEN
3421 fprintf(stderr,"Error: pipes are not supported in this OS\n");
3422 rc = 1;
3423 p->out = stdout;
3424 #else
3425 p->out = popen(zFile + 1, "w");
3426 if( p->out==0 ){
3427 fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
3428 p->out = stdout;
3429 rc = 1;
3430 }else{
3431 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
3432 }
@@ -3433,11 +3506,11 @@
3433 #endif
3434 }else{
3435 p->out = output_file_open(zFile);
3436 if( p->out==0 ){
3437 if( strcmp(zFile,"off")!=0 ){
3438 fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile);
3439 }
3440 p->out = stdout;
3441 rc = 1;
3442 } else {
3443 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
@@ -3446,14 +3519,14 @@
3446 }else
3447
3448 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
3449 int i;
3450 for(i=1; i<nArg; i++){
3451 if( i>1 ) fprintf(p->out, " ");
3452 fprintf(p->out, "%s", azArg[i]);
3453 }
3454 fprintf(p->out, "\n");
3455 }else
3456
3457 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
3458 if( nArg >= 2) {
3459 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
@@ -3468,17 +3541,17 @@
3468 }else
3469
3470 if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
3471 FILE *alt;
3472 if( nArg!=2 ){
3473 fprintf(stderr, "Usage: .read FILE\n");
3474 rc = 1;
3475 goto meta_command_exit;
3476 }
3477 alt = fopen(azArg[1], "rb");
3478 if( alt==0 ){
3479 fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
3480 rc = 1;
3481 }else{
3482 rc = process_input(p, alt);
3483 fclose(alt);
3484 }
@@ -3496,24 +3569,24 @@
3496 zDb = "main";
3497 }else if( nArg==3 ){
3498 zSrcFile = azArg[2];
3499 zDb = azArg[1];
3500 }else{
3501 fprintf(stderr, "Usage: .restore ?DB? FILE\n");
3502 rc = 1;
3503 goto meta_command_exit;
3504 }
3505 rc = sqlite3_open(zSrcFile, &pSrc);
3506 if( rc!=SQLITE_OK ){
3507 fprintf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
3508 sqlite3_close(pSrc);
3509 return 1;
3510 }
3511 open_db(p, 0);
3512 pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
3513 if( pBackup==0 ){
3514 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
3515 sqlite3_close(pSrc);
3516 return 1;
3517 }
3518 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
3519 || rc==SQLITE_BUSY ){
@@ -3524,14 +3597,14 @@
3524 }
3525 sqlite3_backup_finish(pBackup);
3526 if( rc==SQLITE_DONE ){
3527 rc = 0;
3528 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
3529 fprintf(stderr, "Error: source database is busy\n");
3530 rc = 1;
3531 }else{
3532 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
3533 rc = 1;
3534 }
3535 sqlite3_close(pSrc);
3536 }else
3537
@@ -3538,14 +3611,14 @@
3538
3539 if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
3540 if( nArg==2 ){
3541 p->scanstatsOn = booleanValue(azArg[1]);
3542 #ifndef SQLITE_ENABLE_STMT_SCANSTATUS
3543 fprintf(stderr, "Warning: .scanstats not available in this build.\n");
3544 #endif
3545 }else{
3546 fprintf(stderr, "Usage: .scanstats on|off\n");
3547 rc = 1;
3548 }
3549 }else
3550
3551 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
@@ -3608,20 +3681,20 @@
3608 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
3609 "ORDER BY rowid",
3610 callback, &data, &zErrMsg
3611 );
3612 }else{
3613 fprintf(stderr, "Usage: .schema ?LIKE-PATTERN?\n");
3614 rc = 1;
3615 goto meta_command_exit;
3616 }
3617 if( zErrMsg ){
3618 fprintf(stderr,"Error: %s\n", zErrMsg);
3619 sqlite3_free(zErrMsg);
3620 rc = 1;
3621 }else if( rc != SQLITE_OK ){
3622 fprintf(stderr,"Error: querying schema information\n");
3623 rc = 1;
3624 }else{
3625 rc = 0;
3626 }
3627 }else
@@ -3641,28 +3714,28 @@
3641 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
3642 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
3643 int i, v;
3644 for(i=1; i<nArg; i++){
3645 v = booleanValue(azArg[i]);
3646 fprintf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
3647 }
3648 }
3649 if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
3650 int i; sqlite3_int64 v;
3651 for(i=1; i<nArg; i++){
3652 char zBuf[200];
3653 v = integerValue(azArg[i]);
3654 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
3655 fprintf(p->out, "%s", zBuf);
3656 }
3657 }
3658 }else
3659 #endif
3660
3661 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
3662 if( nArg<2 || nArg>3 ){
3663 fprintf(stderr, "Usage: .separator COL ?ROW?\n");
3664 rc = 1;
3665 }
3666 if( nArg>=2 ){
3667 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
3668 "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
@@ -3677,11 +3750,11 @@
3677 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
3678 ){
3679 char *zCmd;
3680 int i, x;
3681 if( nArg<2 ){
3682 fprintf(stderr, "Usage: .system COMMAND\n");
3683 rc = 1;
3684 goto meta_command_exit;
3685 }
3686 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
3687 for(i=2; i<nArg; i++){
@@ -3688,49 +3761,49 @@
3688 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
3689 zCmd, azArg[i]);
3690 }
3691 x = system(zCmd);
3692 sqlite3_free(zCmd);
3693 if( x ) fprintf(stderr, "System command returns %d\n", x);
3694 }else
3695
3696 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
3697 int i;
3698 if( nArg!=1 ){
3699 fprintf(stderr, "Usage: .show\n");
3700 rc = 1;
3701 goto meta_command_exit;
3702 }
3703 fprintf(p->out,"%12.12s: %s\n","echo", p->echoOn ? "on" : "off");
3704 fprintf(p->out,"%12.12s: %s\n","eqp", p->autoEQP ? "on" : "off");
3705 fprintf(p->out,"%9.9s: %s\n","explain", p->normalMode.valid ? "on" :"off");
3706 fprintf(p->out,"%12.12s: %s\n","headers", p->showHeader ? "on" : "off");
3707 fprintf(p->out,"%12.12s: %s\n","mode", modeDescr[p->mode]);
3708 fprintf(p->out,"%12.12s: ", "nullvalue");
3709 output_c_string(p->out, p->nullValue);
3710 fprintf(p->out, "\n");
3711 fprintf(p->out,"%12.12s: %s\n","output",
3712 strlen30(p->outfile) ? p->outfile : "stdout");
3713 fprintf(p->out,"%12.12s: ", "colseparator");
3714 output_c_string(p->out, p->colSeparator);
3715 fprintf(p->out, "\n");
3716 fprintf(p->out,"%12.12s: ", "rowseparator");
3717 output_c_string(p->out, p->rowSeparator);
3718 fprintf(p->out, "\n");
3719 fprintf(p->out,"%12.12s: %s\n","stats", p->statsOn ? "on" : "off");
3720 fprintf(p->out,"%12.12s: ","width");
3721 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
3722 fprintf(p->out,"%d ",p->colWidth[i]);
3723 }
3724 fprintf(p->out,"\n");
3725 }else
3726
3727 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
3728 if( nArg==2 ){
3729 p->statsOn = booleanValue(azArg[1]);
3730 }else{
3731 fprintf(stderr, "Usage: .stats on|off\n");
3732 rc = 1;
3733 }
3734 }else
3735
3736 if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
@@ -3824,13 +3897,14 @@
3824 if( nPrintCol<1 ) nPrintCol = 1;
3825 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
3826 for(i=0; i<nPrintRow; i++){
3827 for(j=i; j<nRow; j+=nPrintRow){
3828 char *zSp = j<nPrintRow ? "" : " ";
3829 fprintf(p->out, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:"");
 
3830 }
3831 fprintf(p->out, "\n");
3832 }
3833 }
3834
3835 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
3836 sqlite3_free(azResult);
@@ -3869,31 +3943,31 @@
3869 for(i=0; i<ArraySize(aCtrl); i++){
3870 if( strncmp(azArg[1], aCtrl[i].zCtrlName, n2)==0 ){
3871 if( testctrl<0 ){
3872 testctrl = aCtrl[i].ctrlCode;
3873 }else{
3874 fprintf(stderr, "ambiguous option name: \"%s\"\n", azArg[1]);
3875 testctrl = -1;
3876 break;
3877 }
3878 }
3879 }
3880 if( testctrl<0 ) testctrl = (int)integerValue(azArg[1]);
3881 if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){
3882 fprintf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]);
3883 }else{
3884 switch(testctrl){
3885
3886 /* sqlite3_test_control(int, db, int) */
3887 case SQLITE_TESTCTRL_OPTIMIZATIONS:
3888 case SQLITE_TESTCTRL_RESERVE:
3889 if( nArg==3 ){
3890 int opt = (int)strtol(azArg[2], 0, 0);
3891 rc2 = sqlite3_test_control(testctrl, p->db, opt);
3892 fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
3893 } else {
3894 fprintf(stderr,"Error: testctrl %s takes a single int option\n",
3895 azArg[1]);
3896 }
3897 break;
3898
3899 /* sqlite3_test_control(int) */
@@ -3901,24 +3975,25 @@
3901 case SQLITE_TESTCTRL_PRNG_RESTORE:
3902 case SQLITE_TESTCTRL_PRNG_RESET:
3903 case SQLITE_TESTCTRL_BYTEORDER:
3904 if( nArg==2 ){
3905 rc2 = sqlite3_test_control(testctrl);
3906 fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
3907 } else {
3908 fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]);
 
3909 }
3910 break;
3911
3912 /* sqlite3_test_control(int, uint) */
3913 case SQLITE_TESTCTRL_PENDING_BYTE:
3914 if( nArg==3 ){
3915 unsigned int opt = (unsigned int)integerValue(azArg[2]);
3916 rc2 = sqlite3_test_control(testctrl, opt);
3917 fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
3918 } else {
3919 fprintf(stderr,"Error: testctrl %s takes a single unsigned"
3920 " int option\n", azArg[1]);
3921 }
3922 break;
3923
3924 /* sqlite3_test_control(int, int) */
@@ -3926,13 +4001,13 @@
3926 case SQLITE_TESTCTRL_ALWAYS:
3927 case SQLITE_TESTCTRL_NEVER_CORRUPT:
3928 if( nArg==3 ){
3929 int opt = booleanValue(azArg[2]);
3930 rc2 = sqlite3_test_control(testctrl, opt);
3931 fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
3932 } else {
3933 fprintf(stderr,"Error: testctrl %s takes a single int option\n",
3934 azArg[1]);
3935 }
3936 break;
3937
3938 /* sqlite3_test_control(int, char *) */
@@ -3939,14 +4014,15 @@
3939 #ifdef SQLITE_N_KEYWORD
3940 case SQLITE_TESTCTRL_ISKEYWORD:
3941 if( nArg==3 ){
3942 const char *opt = azArg[2];
3943 rc2 = sqlite3_test_control(testctrl, opt);
3944 fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
3945 } else {
3946 fprintf(stderr,"Error: testctrl %s takes a single char * option\n",
3947 azArg[1]);
 
3948 }
3949 break;
3950 #endif
3951
3952 case SQLITE_TESTCTRL_IMPOSTER:
@@ -3953,23 +4029,24 @@
3953 if( nArg==5 ){
3954 rc2 = sqlite3_test_control(testctrl, p->db,
3955 azArg[2],
3956 integerValue(azArg[3]),
3957 integerValue(azArg[4]));
3958 fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
3959 }else{
3960 fprintf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
3961 }
3962 break;
3963
3964 case SQLITE_TESTCTRL_BITVEC_TEST:
3965 case SQLITE_TESTCTRL_FAULT_INSTALL:
3966 case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
3967 case SQLITE_TESTCTRL_SCRATCHMALLOC:
3968 default:
3969 fprintf(stderr,"Error: CLI support for testctrl %s not implemented\n",
3970 azArg[1]);
 
3971 break;
3972 }
3973 }
3974 }else
3975
@@ -3980,23 +4057,23 @@
3980
3981 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
3982 if( nArg==2 ){
3983 enableTimer = booleanValue(azArg[1]);
3984 if( enableTimer && !HAS_TIMER ){
3985 fprintf(stderr, "Error: timer not available on this system.\n");
3986 enableTimer = 0;
3987 }
3988 }else{
3989 fprintf(stderr, "Usage: .timer on|off\n");
3990 rc = 1;
3991 }
3992 }else
3993
3994 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
3995 open_db(p, 0);
3996 if( nArg!=2 ){
3997 fprintf(stderr, "Usage: .trace FILE|off\n");
3998 rc = 1;
3999 goto meta_command_exit;
4000 }
4001 output_file_close(p->traceOut);
4002 p->traceOut = output_file_open(azArg[1]);
@@ -4010,87 +4087,87 @@
4010 }else
4011
4012 #if SQLITE_USER_AUTHENTICATION
4013 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
4014 if( nArg<2 ){
4015 fprintf(stderr, "Usage: .user SUBCOMMAND ...\n");
4016 rc = 1;
4017 goto meta_command_exit;
4018 }
4019 open_db(p, 0);
4020 if( strcmp(azArg[1],"login")==0 ){
4021 if( nArg!=4 ){
4022 fprintf(stderr, "Usage: .user login USER PASSWORD\n");
4023 rc = 1;
4024 goto meta_command_exit;
4025 }
4026 rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
4027 (int)strlen(azArg[3]));
4028 if( rc ){
4029 fprintf(stderr, "Authentication failed for user %s\n", azArg[2]);
4030 rc = 1;
4031 }
4032 }else if( strcmp(azArg[1],"add")==0 ){
4033 if( nArg!=5 ){
4034 fprintf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
4035 rc = 1;
4036 goto meta_command_exit;
4037 }
4038 rc = sqlite3_user_add(p->db, azArg[2],
4039 azArg[3], (int)strlen(azArg[3]),
4040 booleanValue(azArg[4]));
4041 if( rc ){
4042 fprintf(stderr, "User-Add failed: %d\n", rc);
4043 rc = 1;
4044 }
4045 }else if( strcmp(azArg[1],"edit")==0 ){
4046 if( nArg!=5 ){
4047 fprintf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
4048 rc = 1;
4049 goto meta_command_exit;
4050 }
4051 rc = sqlite3_user_change(p->db, azArg[2],
4052 azArg[3], (int)strlen(azArg[3]),
4053 booleanValue(azArg[4]));
4054 if( rc ){
4055 fprintf(stderr, "User-Edit failed: %d\n", rc);
4056 rc = 1;
4057 }
4058 }else if( strcmp(azArg[1],"delete")==0 ){
4059 if( nArg!=3 ){
4060 fprintf(stderr, "Usage: .user delete USER\n");
4061 rc = 1;
4062 goto meta_command_exit;
4063 }
4064 rc = sqlite3_user_delete(p->db, azArg[2]);
4065 if( rc ){
4066 fprintf(stderr, "User-Delete failed: %d\n", rc);
4067 rc = 1;
4068 }
4069 }else{
4070 fprintf(stderr, "Usage: .user login|add|edit|delete ...\n");
4071 rc = 1;
4072 goto meta_command_exit;
4073 }
4074 }else
4075 #endif /* SQLITE_USER_AUTHENTICATION */
4076
4077 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
4078 fprintf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
4079 sqlite3_libversion(), sqlite3_sourceid());
4080 }else
4081
4082 if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
4083 const char *zDbName = nArg==2 ? azArg[1] : "main";
4084 sqlite3_vfs *pVfs;
4085 if( p->db ){
4086 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
4087 if( pVfs ){
4088 fprintf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
4089 fprintf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
4090 fprintf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
4091 fprintf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
4092 }
4093 }
4094 }else
4095
4096 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
@@ -4097,11 +4174,11 @@
4097 const char *zDbName = nArg==2 ? azArg[1] : "main";
4098 char *zVfsName = 0;
4099 if( p->db ){
4100 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
4101 if( zVfsName ){
4102 fprintf(p->out, "%s\n", zVfsName);
4103 sqlite3_free(zVfsName);
4104 }
4105 }
4106 }else
4107
@@ -4119,11 +4196,11 @@
4119 p->colWidth[j-1] = (int)integerValue(azArg[j]);
4120 }
4121 }else
4122
4123 {
4124 fprintf(stderr, "Error: unknown command or invalid arguments: "
4125 " \"%s\". Enter \".help\" for help\n", azArg[0]);
4126 rc = 1;
4127 }
4128
4129 meta_command_exit:
@@ -4254,11 +4331,11 @@
4254 nLine = strlen30(zLine);
4255 if( nSql+nLine+2>=nAlloc ){
4256 nAlloc = nSql+nLine+100;
4257 zSql = realloc(zSql, nAlloc);
4258 if( zSql==0 ){
4259 fprintf(stderr, "Error: out of memory\n");
4260 exit(1);
4261 }
4262 }
4263 nSqlPrior = nSql;
4264 if( nSql==0 ){
@@ -4288,19 +4365,19 @@
4288 "Error: near line %d:", startline);
4289 }else{
4290 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
4291 }
4292 if( zErrMsg!=0 ){
4293 fprintf(stderr, "%s %s\n", zPrefix, zErrMsg);
4294 sqlite3_free(zErrMsg);
4295 zErrMsg = 0;
4296 }else{
4297 fprintf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
4298 }
4299 errCnt++;
4300 }else if( p->countChanges ){
4301 fprintf(p->out, "changes: %3d total_changes: %d\n",
4302 sqlite3_changes(p->db), sqlite3_total_changes(p->db));
4303 }
4304 nSql = 0;
4305 if( p->outCount ){
4306 output_reset(p);
@@ -4311,11 +4388,11 @@
4311 nSql = 0;
4312 }
4313 }
4314 if( nSql ){
4315 if( !_all_whitespace(zSql) ){
4316 fprintf(stderr, "Error: incomplete SQL: %s\n", zSql);
4317 errCnt++;
4318 }
4319 }
4320 free(zSql);
4321 free(zLine);
@@ -4402,11 +4479,11 @@
4402 FILE *in = NULL;
4403
4404 if (sqliterc == NULL) {
4405 home_dir = find_home_dir();
4406 if( home_dir==0 ){
4407 fprintf(stderr, "-- warning: cannot find home directory;"
4408 " cannot read ~/.sqliterc\n");
4409 return;
4410 }
4411 sqlite3_initialize();
4412 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
@@ -4413,11 +4490,11 @@
4413 sqliterc = zBuf;
4414 }
4415 in = fopen(sqliterc,"rb");
4416 if( in ){
4417 if( stdin_is_interactive ){
4418 fprintf(stderr,"-- Loading resources from %s\n",sqliterc);
4419 }
4420 process_input(p,in);
4421 fclose(in);
4422 }
4423 sqlite3_free(zBuf);
@@ -4460,18 +4537,18 @@
4460 #ifdef SQLITE_ENABLE_VFSTRACE
4461 " -vfstrace enable tracing of all VFS calls\n"
4462 #endif
4463 ;
4464 static void usage(int showDetail){
4465 fprintf(stderr,
4466 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
4467 "FILENAME is the name of an SQLite database. A new database is created\n"
4468 "if the file does not previously exist.\n", Argv0);
4469 if( showDetail ){
4470 fprintf(stderr, "OPTIONS include:\n%s", zOptions);
4471 }else{
4472 fprintf(stderr, "Use the -help option for additional information\n");
4473 }
4474 exit(1);
4475 }
4476
4477 /*
@@ -4515,11 +4592,11 @@
4515 ** Get the argument to an --option. Throw an error and die if no argument
4516 ** is available.
4517 */
4518 static char *cmdline_option_value(int argc, char **argv, int i){
4519 if( i==argc ){
4520 fprintf(stderr, "%s: Error: missing argument to %s\n",
4521 argv[0], argv[argc-1]);
4522 exit(1);
4523 }
4524 return argv[i];
4525 }
@@ -4535,20 +4612,21 @@
4535 int nCmd = 0;
4536 char **azCmd = 0;
4537
4538 #if USE_SYSTEM_SQLITE+0!=1
4539 if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
4540 fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
4541 sqlite3_sourceid(), SQLITE_SOURCE_ID);
4542 exit(1);
4543 }
4544 #endif
4545 setBinaryMode(stdin);
4546 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
4547 Argv0 = argv[0];
4548 main_init(&data);
4549 stdin_is_interactive = isatty(0);
 
4550
4551 /* Make sure we have a valid signal handler early, before anything
4552 ** else is done.
4553 */
4554 #ifdef SIGINT
@@ -4583,11 +4661,11 @@
4583 ** mean that nothing is read from stdin */
4584 readStdin = 0;
4585 nCmd++;
4586 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
4587 if( azCmd==0 ){
4588 fprintf(stderr, "out of memory\n");
4589 exit(1);
4590 }
4591 azCmd[nCmd-1] = z;
4592 }
4593 }
@@ -4665,21 +4743,21 @@
4665 }else if( strcmp(z,"-vfs")==0 ){
4666 sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i));
4667 if( pVfs ){
4668 sqlite3_vfs_register(pVfs, 1);
4669 }else{
4670 fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]);
4671 exit(1);
4672 }
4673 }
4674 }
4675 if( data.zDbFilename==0 ){
4676 #ifndef SQLITE_OMIT_MEMORYDB
4677 data.zDbFilename = ":memory:";
4678 warnInmemoryDb = argc==1;
4679 #else
4680 fprintf(stderr,"%s: Error: no database filename specified\n", Argv0);
4681 return 1;
4682 #endif
4683 }
4684 data.out = stdout;
4685
@@ -4797,20 +4875,20 @@
4797 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
4798 }else{
4799 open_db(&data, 0);
4800 rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg);
4801 if( zErrMsg!=0 ){
4802 fprintf(stderr,"Error: %s\n", zErrMsg);
4803 if( bail_on_error ) return rc!=0 ? rc : 1;
4804 }else if( rc!=0 ){
4805 fprintf(stderr,"Error: unable to process SQL \"%s\"\n", z);
4806 if( bail_on_error ) return rc;
4807 }
4808 }
4809 }else{
4810 fprintf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
4811 fprintf(stderr,"Use -help for a list of options.\n");
4812 return 1;
4813 }
4814 }
4815
4816 if( !readStdin ){
@@ -4824,14 +4902,14 @@
4824 if( rc ) return rc==2 ? 0 : rc;
4825 }else{
4826 open_db(&data, 0);
4827 rc = shell_exec(data.db, azCmd[i], shell_callback, &data, &zErrMsg);
4828 if( zErrMsg!=0 ){
4829 fprintf(stderr,"Error: %s\n", zErrMsg);
4830 return rc!=0 ? rc : 1;
4831 }else if( rc!=0 ){
4832 fprintf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
4833 return rc;
4834 }
4835 }
4836 }
4837 free(azCmd);
4838
--- src/shell.c
+++ src/shell.c
@@ -327,10 +327,17 @@
327 ** Threat stdin as an interactive input if the following variable
328 ** is true. Otherwise, assume stdin is connected to a file or pipe.
329 */
330 static int stdin_is_interactive = 1;
331
332 /*
333 ** On Windows systems we have to know if standard output is a console
334 ** in order to translate UTF-8 into MBCS. The following variable is
335 ** true if translation is required.
336 */
337 static int stdout_is_console = 1;
338
339 /*
340 ** The following is the open SQLite database. We make a pointer
341 ** to this database a static variable so that it can be accessed
342 ** by the SIGINT handler to interrupt database processing.
343 */
@@ -427,10 +434,20 @@
434 UNUSED_PARAMETER(argc);
435 UNUSED_PARAMETER(argv);
436 sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC);
437 }
438
439
440 /*
441 ** Compute a string length that is limited to what can be stored in
442 ** lower 30 bits of a 32-bit signed integer.
443 */
444 static int strlen30(const char *z){
445 const char *z2 = z;
446 while( *z2 ){ z2++; }
447 return 0x3fffffff & (int)(z2 - z);
448 }
449
450 /*
451 ** This routine reads a line of text from FILE in, stores
452 ** the text in memory obtained from malloc() and returns a pointer
453 ** to the text. NULL is returned at end of file, or if malloc()
@@ -463,10 +480,30 @@
480 if( n>0 && zLine[n-1]=='\r' ) n--;
481 zLine[n] = 0;
482 break;
483 }
484 }
485 #if defined(_WIN32) || defined(WIN32)
486 /* For interactive input on Windows systems, translate the
487 ** multi-byte characterset characters into UTF-8. */
488 if( stdin_is_interactive ){
489 extern char *sqlite3_win32_mbcs_to_utf8(const char*);
490 char *zTrans = sqlite3_win32_mbcs_to_utf8(zLine);
491 if( zTrans ){
492 int nTrans = strlen30(zTrans)+1;
493 if( nTrans>nLine ){
494 zLine = realloc(zLine, nTrans);
495 if( zLine==0 ){
496 sqlite3_free(zTrans);
497 return 0;
498 }
499 }
500 memcpy(zLine, zTrans, nTrans);
501 sqlite3_free(zTrans);
502 }
503 }
504 #endif /* defined(_WIN32) || defined(WIN32) */
505 return zLine;
506 }
507
508 /*
509 ** Retrieve a single line of input text.
@@ -500,10 +537,43 @@
537 #endif
538 }
539 return zResult;
540 }
541
542 /*
543 ** Render output like fprintf(). Except, if the output is going to the
544 ** console and if this is running on a Windows machine, translate the
545 ** output from UTF-8 into MBCS.
546 */
547 #if defined(_WIN32) || defined(WIN32)
548 void utf8_printf(FILE *out, const char *zFormat, ...){
549 va_list ap;
550 va_start(ap, zFormat);
551 if( stdout_is_console && (out==stdout || out==stderr) ){
552 extern char *sqlite3_win32_utf8_to_mbcs(const char*);
553 char *z1 = sqlite3_vmprintf(zFormat, ap);
554 char *z2 = sqlite3_win32_utf8_to_mbcs(z1);
555 sqlite3_free(z1);
556 fputs(z2, out);
557 sqlite3_free(z2);
558 }else{
559 vfprintf(out, zFormat, ap);
560 }
561 va_end(ap);
562 }
563 #elif !defined(utf8_printf)
564 # define utf8_printf fprintf
565 #endif
566
567 /*
568 ** Render output like fprintf(). This should not be used on anything that
569 ** includes string formatting (e.g. "%s").
570 */
571 #if !defined(raw_printf)
572 # define raw_printf fprintf
573 #endif
574
575 /*
576 ** Shell output mode information from before ".explain on",
577 ** saved so that it can be restored by ".explain off"
578 */
579 typedef struct SavedModeInfo SavedModeInfo;
@@ -605,39 +675,29 @@
675 /*
676 ** Number of elements in an array
677 */
678 #define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
679
 
 
 
 
 
 
 
 
 
 
680 /*
681 ** A callback for the sqlite3_log() interface.
682 */
683 static void shellLog(void *pArg, int iErrCode, const char *zMsg){
684 ShellState *p = (ShellState*)pArg;
685 if( p->pLog==0 ) return;
686 utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
687 fflush(p->pLog);
688 }
689
690 /*
691 ** Output the given string as a hex-encoded blob (eg. X'1234' )
692 */
693 static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
694 int i;
695 char *zBlob = (char *)pBlob;
696 raw_printf(out,"X'");
697 for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
698 raw_printf(out,"'");
699 }
700
701 /*
702 ** Output the given string as a quoted string using SQL quoting conventions.
703 */
@@ -647,27 +707,27 @@
707 setBinaryMode(out);
708 for(i=0; z[i]; i++){
709 if( z[i]=='\'' ) nSingle++;
710 }
711 if( nSingle==0 ){
712 utf8_printf(out,"'%s'",z);
713 }else{
714 raw_printf(out,"'");
715 while( *z ){
716 for(i=0; z[i] && z[i]!='\''; i++){}
717 if( i==0 ){
718 raw_printf(out,"''");
719 z++;
720 }else if( z[i]=='\'' ){
721 utf8_printf(out,"%.*s''",i,z);
722 z += i+1;
723 }else{
724 utf8_printf(out,"%s",z);
725 break;
726 }
727 }
728 raw_printf(out,"'");
729 }
730 setTextMode(out);
731 }
732
733 /*
@@ -691,11 +751,11 @@
751 fputc('n', out);
752 }else if( c=='\r' ){
753 fputc('\\', out);
754 fputc('r', out);
755 }else if( !isprint(c&0xff) ){
756 raw_printf(out, "\\%03o", c&0xff);
757 }else{
758 fputc(c, out);
759 }
760 }
761 fputc('"', out);
@@ -715,22 +775,22 @@
775 && z[i]!='>'
776 && z[i]!='\"'
777 && z[i]!='\'';
778 i++){}
779 if( i>0 ){
780 utf8_printf(out,"%.*s",i,z);
781 }
782 if( z[i]=='<' ){
783 raw_printf(out,"&lt;");
784 }else if( z[i]=='&' ){
785 raw_printf(out,"&amp;");
786 }else if( z[i]=='>' ){
787 raw_printf(out,"&gt;");
788 }else if( z[i]=='\"' ){
789 raw_printf(out,"&quot;");
790 }else if( z[i]=='\'' ){
791 raw_printf(out,"&#39;");
792 }else{
793 break;
794 }
795 z += i + 1;
796 }
@@ -766,11 +826,11 @@
826 ** is only issued if bSep is true.
827 */
828 static void output_csv(ShellState *p, const char *z, int bSep){
829 FILE *out = p->out;
830 if( z==0 ){
831 utf8_printf(out,"%s",p->nullValue);
832 }else{
833 int i;
834 int nSep = strlen30(p->colSeparator);
835 for(i=0; z[i]; i++){
836 if( needCsvQuote[((unsigned char*)z)[i]]
@@ -786,15 +846,15 @@
846 if( z[i]=='"' ) putc('"', out);
847 putc(z[i], out);
848 }
849 putc('"', out);
850 }else{
851 utf8_printf(out, "%s", z);
852 }
853 }
854 if( bSep ){
855 utf8_printf(p->out, "%s", p->colSeparator);
856 }
857 }
858
859 #ifdef SIGINT
860 /*
@@ -828,13 +888,13 @@
888 if( azArg==0 ) break;
889 for(i=0; i<nArg; i++){
890 int len = strlen30(azCol[i] ? azCol[i] : "");
891 if( len>w ) w = len;
892 }
893 if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
894 for(i=0; i<nArg; i++){
895 utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
896 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
897 }
898 break;
899 }
900 case MODE_Explain:
@@ -856,14 +916,14 @@
916 if( i<ArraySize(p->actualWidth) ){
917 p->actualWidth[i] = w;
918 }
919 if( p->showHeader ){
920 if( w<0 ){
921 utf8_printf(p->out,"%*.*s%s",-w,-w,azCol[i],
922 i==nArg-1 ? p->rowSeparator : " ");
923 }else{
924 utf8_printf(p->out,"%-*.*s%s",w,w,azCol[i],
925 i==nArg-1 ? p->rowSeparator : " ");
926 }
927 }
928 }
929 if( p->showHeader ){
@@ -873,11 +933,12 @@
933 w = p->actualWidth[i];
934 if( w<0 ) w = -w;
935 }else{
936 w = 10;
937 }
938 utf8_printf(p->out,"%-*.*s%s",w,w,
939 "----------------------------------------------------------"
940 "----------------------------------------------------------",
941 i==nArg-1 ? p->rowSeparator : " ");
942 }
943 }
944 }
@@ -892,20 +953,20 @@
953 if( p->mode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){
954 w = strlen30(azArg[i]);
955 }
956 if( i==1 && p->aiIndent && p->pStmt ){
957 if( p->iIndent<p->nIndent ){
958 utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
959 }
960 p->iIndent++;
961 }
962 if( w<0 ){
963 utf8_printf(p->out,"%*.*s%s",-w,-w,
964 azArg[i] ? azArg[i] : p->nullValue,
965 i==nArg-1 ? p->rowSeparator : " ");
966 }else{
967 utf8_printf(p->out,"%-*.*s%s",w,w,
968 azArg[i] ? azArg[i] : p->nullValue,
969 i==nArg-1 ? p->rowSeparator : " ");
970 }
971 }
972 break;
@@ -912,134 +973,134 @@
973 }
974 case MODE_Semi:
975 case MODE_List: {
976 if( p->cnt++==0 && p->showHeader ){
977 for(i=0; i<nArg; i++){
978 utf8_printf(p->out,"%s%s",azCol[i],
979 i==nArg-1 ? p->rowSeparator : p->colSeparator);
980 }
981 }
982 if( azArg==0 ) break;
983 for(i=0; i<nArg; i++){
984 char *z = azArg[i];
985 if( z==0 ) z = p->nullValue;
986 utf8_printf(p->out, "%s", z);
987 if( i<nArg-1 ){
988 utf8_printf(p->out, "%s", p->colSeparator);
989 }else if( p->mode==MODE_Semi ){
990 utf8_printf(p->out, ";%s", p->rowSeparator);
991 }else{
992 utf8_printf(p->out, "%s", p->rowSeparator);
993 }
994 }
995 break;
996 }
997 case MODE_Html: {
998 if( p->cnt++==0 && p->showHeader ){
999 raw_printf(p->out,"<TR>");
1000 for(i=0; i<nArg; i++){
1001 raw_printf(p->out,"<TH>");
1002 output_html_string(p->out, azCol[i]);
1003 raw_printf(p->out,"</TH>\n");
1004 }
1005 raw_printf(p->out,"</TR>\n");
1006 }
1007 if( azArg==0 ) break;
1008 raw_printf(p->out,"<TR>");
1009 for(i=0; i<nArg; i++){
1010 raw_printf(p->out,"<TD>");
1011 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
1012 raw_printf(p->out,"</TD>\n");
1013 }
1014 raw_printf(p->out,"</TR>\n");
1015 break;
1016 }
1017 case MODE_Tcl: {
1018 if( p->cnt++==0 && p->showHeader ){
1019 for(i=0; i<nArg; i++){
1020 output_c_string(p->out,azCol[i] ? azCol[i] : "");
1021 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
1022 }
1023 utf8_printf(p->out, "%s", p->rowSeparator);
1024 }
1025 if( azArg==0 ) break;
1026 for(i=0; i<nArg; i++){
1027 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
1028 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
1029 }
1030 utf8_printf(p->out, "%s", p->rowSeparator);
1031 break;
1032 }
1033 case MODE_Csv: {
1034 setBinaryMode(p->out);
1035 if( p->cnt++==0 && p->showHeader ){
1036 for(i=0; i<nArg; i++){
1037 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
1038 }
1039 utf8_printf(p->out, "%s", p->rowSeparator);
1040 }
1041 if( nArg>0 ){
1042 for(i=0; i<nArg; i++){
1043 output_csv(p, azArg[i], i<nArg-1);
1044 }
1045 utf8_printf(p->out, "%s", p->rowSeparator);
1046 }
1047 setTextMode(p->out);
1048 break;
1049 }
1050 case MODE_Insert: {
1051 p->cnt++;
1052 if( azArg==0 ) break;
1053 utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
1054 if( p->showHeader ){
1055 raw_printf(p->out,"(");
1056 for(i=0; i<nArg; i++){
1057 char *zSep = i>0 ? ",": "";
1058 utf8_printf(p->out, "%s%s", zSep, azCol[i]);
1059 }
1060 raw_printf(p->out,")");
1061 }
1062 raw_printf(p->out," VALUES(");
1063 for(i=0; i<nArg; i++){
1064 char *zSep = i>0 ? ",": "";
1065 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
1066 utf8_printf(p->out,"%sNULL",zSep);
1067 }else if( aiType && aiType[i]==SQLITE_TEXT ){
1068 if( zSep[0] ) utf8_printf(p->out,"%s",zSep);
1069 output_quoted_string(p->out, azArg[i]);
1070 }else if( aiType && (aiType[i]==SQLITE_INTEGER
1071 || aiType[i]==SQLITE_FLOAT) ){
1072 utf8_printf(p->out,"%s%s",zSep, azArg[i]);
1073 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
1074 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
1075 int nBlob = sqlite3_column_bytes(p->pStmt, i);
1076 if( zSep[0] ) utf8_printf(p->out,"%s",zSep);
1077 output_hex_blob(p->out, pBlob, nBlob);
1078 }else if( isNumber(azArg[i], 0) ){
1079 utf8_printf(p->out,"%s%s",zSep, azArg[i]);
1080 }else{
1081 if( zSep[0] ) utf8_printf(p->out,"%s",zSep);
1082 output_quoted_string(p->out, azArg[i]);
1083 }
1084 }
1085 raw_printf(p->out,");\n");
1086 break;
1087 }
1088 case MODE_Ascii: {
1089 if( p->cnt++==0 && p->showHeader ){
1090 for(i=0; i<nArg; i++){
1091 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
1092 utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
1093 }
1094 utf8_printf(p->out, "%s", p->rowSeparator);
1095 }
1096 if( azArg==0 ) break;
1097 for(i=0; i<nArg; i++){
1098 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
1099 utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
1100 }
1101 utf8_printf(p->out, "%s", p->rowSeparator);
1102 break;
1103 }
1104 }
1105 return 0;
1106 }
@@ -1076,11 +1137,11 @@
1137 }
1138 }
1139 if( needQuote ) n += 2;
1140 z = p->zDestTable = malloc( n+1 );
1141 if( z==0 ){
1142 raw_printf(stderr,"Error: out of memory\n");
1143 exit(1);
1144 }
1145 n = 0;
1146 if( needQuote ) z[n++] = '\'';
1147 for(i=0; zName[i]; i++){
@@ -1157,38 +1218,40 @@
1218 int nResult;
1219 int i;
1220 const char *z;
1221 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
1222 if( rc!=SQLITE_OK || !pSelect ){
1223 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
1224 sqlite3_errmsg(p->db));
1225 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
1226 return rc;
1227 }
1228 rc = sqlite3_step(pSelect);
1229 nResult = sqlite3_column_count(pSelect);
1230 while( rc==SQLITE_ROW ){
1231 if( zFirstRow ){
1232 utf8_printf(p->out, "%s", zFirstRow);
1233 zFirstRow = 0;
1234 }
1235 z = (const char*)sqlite3_column_text(pSelect, 0);
1236 utf8_printf(p->out, "%s", z);
1237 for(i=1; i<nResult; i++){
1238 utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
1239 }
1240 if( z==0 ) z = "";
1241 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
1242 if( z[0] ){
1243 raw_printf(p->out, "\n;\n");
1244 }else{
1245 raw_printf(p->out, ";\n");
1246 }
1247 rc = sqlite3_step(pSelect);
1248 }
1249 rc = sqlite3_finalize(pSelect);
1250 if( rc!=SQLITE_OK ){
1251 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
1252 sqlite3_errmsg(p->db));
1253 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
1254 }
1255 return rc;
1256 }
1257
@@ -1219,107 +1282,115 @@
1282
1283 if( pArg && pArg->out ){
1284
1285 iHiwtr = iCur = -1;
1286 sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset);
1287 raw_printf(pArg->out,
1288 "Memory Used: %d (max %d) bytes\n",
1289 iCur, iHiwtr);
1290 iHiwtr = iCur = -1;
1291 sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset);
1292 raw_printf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n",
1293 iCur, iHiwtr);
1294 if( pArg->shellFlgs & SHFLG_Pagecache ){
1295 iHiwtr = iCur = -1;
1296 sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset);
1297 raw_printf(pArg->out,
1298 "Number of Pcache Pages Used: %d (max %d) pages\n",
1299 iCur, iHiwtr);
1300 }
1301 iHiwtr = iCur = -1;
1302 sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset);
1303 raw_printf(pArg->out,
1304 "Number of Pcache Overflow Bytes: %d (max %d) bytes\n",
1305 iCur, iHiwtr);
1306 if( pArg->shellFlgs & SHFLG_Scratch ){
1307 iHiwtr = iCur = -1;
1308 sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset);
1309 raw_printf(pArg->out,
1310 "Number of Scratch Allocations Used: %d (max %d)\n",
1311 iCur, iHiwtr);
1312 }
1313 iHiwtr = iCur = -1;
1314 sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset);
1315 raw_printf(pArg->out,
1316 "Number of Scratch Overflow Bytes: %d (max %d) bytes\n",
1317 iCur, iHiwtr);
1318 iHiwtr = iCur = -1;
1319 sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset);
1320 raw_printf(pArg->out, "Largest Allocation: %d bytes\n",
1321 iHiwtr);
1322 iHiwtr = iCur = -1;
1323 sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset);
1324 raw_printf(pArg->out, "Largest Pcache Allocation: %d bytes\n",
1325 iHiwtr);
1326 iHiwtr = iCur = -1;
1327 sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset);
1328 raw_printf(pArg->out, "Largest Scratch Allocation: %d bytes\n",
1329 iHiwtr);
1330 #ifdef YYTRACKMAXSTACKDEPTH
1331 iHiwtr = iCur = -1;
1332 sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset);
1333 raw_printf(pArg->out, "Deepest Parser Stack: %d (max %d)\n",
1334 iCur, iHiwtr);
1335 #endif
1336 }
1337
1338 if( pArg && pArg->out && db ){
1339 if( pArg->shellFlgs & SHFLG_Lookaside ){
1340 iHiwtr = iCur = -1;
1341 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
1342 &iCur, &iHiwtr, bReset);
1343 raw_printf(pArg->out,
1344 "Lookaside Slots Used: %d (max %d)\n",
1345 iCur, iHiwtr);
1346 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
1347 &iCur, &iHiwtr, bReset);
1348 raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
1349 iHiwtr);
1350 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
1351 &iCur, &iHiwtr, bReset);
1352 raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
1353 iHiwtr);
1354 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
1355 &iCur, &iHiwtr, bReset);
1356 raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
1357 iHiwtr);
1358 }
1359 iHiwtr = iCur = -1;
1360 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
1361 raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
1362 iCur);
1363 iHiwtr = iCur = -1;
1364 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
1365 raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
1366 iHiwtr = iCur = -1;
1367 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
1368 raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
1369 iHiwtr = iCur = -1;
1370 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
1371 raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
1372 iHiwtr = iCur = -1;
1373 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
1374 raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
1375 iCur);
1376 iHiwtr = iCur = -1;
1377 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
1378 raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
1379 iCur);
1380 }
1381
1382 if( pArg && pArg->out && db && pArg->pStmt ){
1383 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
1384 bReset);
1385 raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
1386 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
1387 raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
1388 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
1389 raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
1390 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
1391 raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
1392 }
1393
1394 /* Do not remove this machine readable comment: extra-stats-output-here */
1395
1396 return 0;
@@ -1335,11 +1406,11 @@
1406 #ifndef SQLITE_ENABLE_STMT_SCANSTATUS
1407 UNUSED_PARAMETER(db);
1408 UNUSED_PARAMETER(pArg);
1409 #else
1410 int i, k, n, mx;
1411 raw_printf(pArg->out, "-------- scanstats --------\n");
1412 mx = 0;
1413 for(k=0; k<=mx; k++){
1414 double rEstLoop = 1.0;
1415 for(i=n=0; 1; i++){
1416 sqlite3_stmt *p = pArg->pStmt;
@@ -1353,25 +1424,25 @@
1424 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
1425 if( iSid>mx ) mx = iSid;
1426 if( iSid!=k ) continue;
1427 if( n==0 ){
1428 rEstLoop = (double)nLoop;
1429 if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
1430 }
1431 n++;
1432 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
1433 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
1434 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
1435 utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
1436 rEstLoop *= rEst;
1437 raw_printf(pArg->out,
1438 " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
1439 nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
1440 );
1441 }
1442 }
1443 raw_printf(pArg->out, "---------------------------\n");
1444 #endif
1445 }
1446
1447 /*
1448 ** Parameter azArray points to a zero-terminated array of strings. zStr
@@ -1520,11 +1591,11 @@
1591 }
1592
1593 /* echo the sql statement if echo on */
1594 if( pArg && pArg->echoOn ){
1595 const char *zStmtSql = sqlite3_sql(pStmt);
1596 utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
1597 }
1598
1599 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
1600 if( pArg && pArg->autoEQP ){
1601 sqlite3_stmt *pExplain;
@@ -1531,14 +1602,14 @@
1602 char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s",
1603 sqlite3_sql(pStmt));
1604 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
1605 if( rc==SQLITE_OK ){
1606 while( sqlite3_step(pExplain)==SQLITE_ROW ){
1607 raw_printf(pArg->out,"--EQP-- %d,",sqlite3_column_int(pExplain, 0));
1608 raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1));
1609 raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2));
1610 utf8_printf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
1611 }
1612 }
1613 sqlite3_finalize(pExplain);
1614 sqlite3_free(zEQP);
1615 }
@@ -1662,28 +1733,28 @@
1733 zSql = azArg[2];
1734
1735 if( strcmp(zTable, "sqlite_sequence")==0 ){
1736 zPrepStmt = "DELETE FROM sqlite_sequence;\n";
1737 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
1738 raw_printf(p->out, "ANALYZE sqlite_master;\n");
1739 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
1740 return 0;
1741 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
1742 char *zIns;
1743 if( !p->writableSchema ){
1744 raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
1745 p->writableSchema = 1;
1746 }
1747 zIns = sqlite3_mprintf(
1748 "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
1749 "VALUES('table','%q','%q',0,'%q');",
1750 zTable, zTable, zSql);
1751 utf8_printf(p->out, "%s\n", zIns);
1752 sqlite3_free(zIns);
1753 return 0;
1754 }else{
1755 utf8_printf(p->out, "%s;\n", zSql);
1756 }
1757
1758 if( strcmp(zType, "table")==0 ){
1759 sqlite3_stmt *pTableInfo = 0;
1760 char *zSelect = 0;
@@ -1756,22 +1827,22 @@
1827 char *zErr = 0;
1828 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
1829 if( rc==SQLITE_CORRUPT ){
1830 char *zQ2;
1831 int len = strlen30(zQuery);
1832 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
1833 if( zErr ){
1834 utf8_printf(p->out, "/****** %s ******/\n", zErr);
1835 sqlite3_free(zErr);
1836 zErr = 0;
1837 }
1838 zQ2 = malloc( len+100 );
1839 if( zQ2==0 ) return rc;
1840 sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
1841 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
1842 if( rc ){
1843 utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
1844 }else{
1845 rc = SQLITE_CORRUPT;
1846 }
1847 sqlite3_free(zErr);
1848 free(zQ2);
@@ -1932,11 +2003,11 @@
2003 if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){
2004 sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0,
2005 shellstaticFunc, 0, 0);
2006 }
2007 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
2008 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
2009 p->zDbFilename, sqlite3_errmsg(p->db));
2010 if( keepAlive ) return;
2011 exit(1);
2012 }
2013 #ifndef SQLITE_OMIT_LOAD_EXTENSION
@@ -2082,11 +2153,11 @@
2153 return 1;
2154 }
2155 if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
2156 return 0;
2157 }
2158 utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
2159 zArg);
2160 return 0;
2161 }
2162
2163 /*
@@ -2110,11 +2181,11 @@
2181 }else if( strcmp(zFile, "off")==0 ){
2182 f = 0;
2183 }else{
2184 f = fopen(zFile, "wb");
2185 if( f==0 ){
2186 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
2187 }
2188 }
2189 return f;
2190 }
2191
@@ -2124,11 +2195,11 @@
2195 static void sql_trace_callback(void *pArg, const char *z){
2196 FILE *f = (FILE*)pArg;
2197 if( f ){
2198 int i = (int)strlen(z);
2199 while( i>0 && z[i-1]==';' ){ i--; }
2200 utf8_printf(f, "%.*s;\n", i, z);
2201 }
2202 }
2203
2204 /*
2205 ** A no-op routine that runs with the ".breakpoint" doc-command. This is
@@ -2159,11 +2230,11 @@
2230 static void import_append_char(ImportCtx *p, int c){
2231 if( p->n+1>=p->nAlloc ){
2232 p->nAlloc += p->nAlloc + 100;
2233 p->z = sqlite3_realloc64(p->z, p->nAlloc);
2234 if( p->z==0 ){
2235 raw_printf(stderr, "out of memory\n");
2236 exit(1);
2237 }
2238 }
2239 p->z[p->n++] = (char)c;
2240 }
@@ -2213,15 +2284,15 @@
2284 do{ p->n--; }while( p->z[p->n]!=cQuote );
2285 p->cTerm = c;
2286 break;
2287 }
2288 if( pc==cQuote && c!='\r' ){
2289 utf8_printf(stderr, "%s:%d: unescaped %c character\n",
2290 p->zFile, p->nLine, cQuote);
2291 }
2292 if( c==EOF ){
2293 utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
2294 p->zFile, startLine, cQuote);
2295 p->cTerm = c;
2296 break;
2297 }
2298 import_append_char(p, c);
@@ -2299,19 +2370,19 @@
2370 const int spinRate = 10000;
2371
2372 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
2373 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
2374 if( rc ){
2375 utf8_printf(stderr, "Error %d: %s on [%s]\n",
2376 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
2377 zQuery);
2378 goto end_data_xfer;
2379 }
2380 n = sqlite3_column_count(pQuery);
2381 zInsert = sqlite3_malloc64(200 + nTable + n*3);
2382 if( zInsert==0 ){
2383 raw_printf(stderr, "out of memory\n");
2384 goto end_data_xfer;
2385 }
2386 sqlite3_snprintf(200+nTable,zInsert,
2387 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
2388 i = (int)strlen(zInsert);
@@ -2320,11 +2391,11 @@
2391 i += 2;
2392 }
2393 memcpy(zInsert+i, ");", 3);
2394 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
2395 if( rc ){
2396 utf8_printf(stderr, "Error %d: %s on [%s]\n",
2397 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
2398 zQuery);
2399 goto end_data_xfer;
2400 }
2401 for(k=0; k<2; k++){
@@ -2357,11 +2428,11 @@
2428 }
2429 }
2430 } /* End for */
2431 rc = sqlite3_step(pInsert);
2432 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
2433 utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
2434 sqlite3_errmsg(newDb));
2435 }
2436 sqlite3_reset(pInsert);
2437 cnt++;
2438 if( (cnt%spinRate)==0 ){
@@ -2374,11 +2445,11 @@
2445 sqlite3_free(zQuery);
2446 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
2447 zTable);
2448 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
2449 if( rc ){
2450 utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
2451 break;
2452 }
2453 } /* End for(k=0...) */
2454
2455 end_data_xfer:
@@ -2410,11 +2481,11 @@
2481
2482 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
2483 " WHERE %s", zWhere);
2484 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
2485 if( rc ){
2486 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
2487 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
2488 zQuery);
2489 goto end_schema_xfer;
2490 }
2491 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
@@ -2421,11 +2492,11 @@
2492 zName = sqlite3_column_text(pQuery, 0);
2493 zSql = sqlite3_column_text(pQuery, 1);
2494 printf("%s... ", zName); fflush(stdout);
2495 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
2496 if( zErrMsg ){
2497 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
2498 sqlite3_free(zErrMsg);
2499 zErrMsg = 0;
2500 }
2501 if( xForEach ){
2502 xForEach(p, newDb, (const char*)zName);
@@ -2437,11 +2508,11 @@
2508 sqlite3_free(zQuery);
2509 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
2510 " WHERE %s ORDER BY rowid DESC", zWhere);
2511 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
2512 if( rc ){
2513 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
2514 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
2515 zQuery);
2516 goto end_schema_xfer;
2517 }
2518 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
@@ -2448,11 +2519,11 @@
2519 zName = sqlite3_column_text(pQuery, 0);
2520 zSql = sqlite3_column_text(pQuery, 1);
2521 printf("%s... ", zName); fflush(stdout);
2522 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
2523 if( zErrMsg ){
2524 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
2525 sqlite3_free(zErrMsg);
2526 zErrMsg = 0;
2527 }
2528 if( xForEach ){
2529 xForEach(p, newDb, (const char*)zName);
@@ -2472,16 +2543,16 @@
2543 */
2544 static void tryToClone(ShellState *p, const char *zNewDb){
2545 int rc;
2546 sqlite3 *newDb = 0;
2547 if( access(zNewDb,0)==0 ){
2548 utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
2549 return;
2550 }
2551 rc = sqlite3_open(zNewDb, &newDb);
2552 if( rc ){
2553 utf8_printf(stderr, "Cannot create output database: %s\n",
2554 sqlite3_errmsg(newDb));
2555 }else{
2556 sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
2557 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
2558 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
@@ -2574,31 +2645,31 @@
2645 if( pFile==0 || pFile->pMethods==0 || pFile->pMethods->xRead==0 ){
2646 return 1;
2647 }
2648 i = pFile->pMethods->xRead(pFile, aHdr, 100, 0);
2649 if( i!=SQLITE_OK ){
2650 raw_printf(stderr, "unable to read database header\n");
2651 return 1;
2652 }
2653 i = get2byteInt(aHdr+16);
2654 if( i==1 ) i = 65536;
2655 utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
2656 utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
2657 utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
2658 utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
2659 for(i=0; i<ArraySize(aField); i++){
2660 int ofst = aField[i].ofst;
2661 unsigned int val = get4byteInt(aHdr + ofst);
2662 utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
2663 switch( ofst ){
2664 case 56: {
2665 if( val==1 ) raw_printf(p->out, " (utf8)");
2666 if( val==2 ) raw_printf(p->out, " (utf16le)");
2667 if( val==3 ) raw_printf(p->out, " (utf16be)");
2668 }
2669 }
2670 raw_printf(p->out, "\n");
2671 }
2672 if( zDb==0 ){
2673 zSchemaTab = sqlite3_mprintf("main.sqlite_master");
2674 }else if( strcmp(zDb,"temp")==0 ){
2675 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master");
@@ -2607,11 +2678,11 @@
2678 }
2679 for(i=0; i<ArraySize(aQuery); i++){
2680 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
2681 int val = db_int(p, zSql);
2682 sqlite3_free(zSql);
2683 utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
2684 }
2685 sqlite3_free(zSchemaTab);
2686 return 0;
2687 }
2688
@@ -2618,19 +2689,19 @@
2689 /*
2690 ** Print the current sqlite3_errmsg() value to stderr and return 1.
2691 */
2692 static int shellDatabaseError(sqlite3 *db){
2693 const char *zErr = sqlite3_errmsg(db);
2694 utf8_printf(stderr, "Error: %s\n", zErr);
2695 return 1;
2696 }
2697
2698 /*
2699 ** Print an out-of-memory message to stderr and return 1.
2700 */
2701 static int shellNomemError(void){
2702 raw_printf(stderr, "Error: out of memory\n");
2703 return 1;
2704 }
2705
2706 /*
2707 ** If an input line begins with "." then invoke this routine to
@@ -2686,57 +2757,57 @@
2757 const char *z = azArg[j];
2758 if( z[0]=='-' ){
2759 while( z[0]=='-' ) z++;
2760 /* No options to process at this time */
2761 {
2762 utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
2763 return 1;
2764 }
2765 }else if( zDestFile==0 ){
2766 zDestFile = azArg[j];
2767 }else if( zDb==0 ){
2768 zDb = zDestFile;
2769 zDestFile = azArg[j];
2770 }else{
2771 raw_printf(stderr, "too many arguments to .backup\n");
2772 return 1;
2773 }
2774 }
2775 if( zDestFile==0 ){
2776 raw_printf(stderr, "missing FILENAME argument on .backup\n");
2777 return 1;
2778 }
2779 if( zDb==0 ) zDb = "main";
2780 rc = sqlite3_open(zDestFile, &pDest);
2781 if( rc!=SQLITE_OK ){
2782 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
2783 sqlite3_close(pDest);
2784 return 1;
2785 }
2786 open_db(p, 0);
2787 pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
2788 if( pBackup==0 ){
2789 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
2790 sqlite3_close(pDest);
2791 return 1;
2792 }
2793 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
2794 sqlite3_backup_finish(pBackup);
2795 if( rc==SQLITE_DONE ){
2796 rc = 0;
2797 }else{
2798 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
2799 rc = 1;
2800 }
2801 sqlite3_close(pDest);
2802 }else
2803
2804 if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
2805 if( nArg==2 ){
2806 bail_on_error = booleanValue(azArg[1]);
2807 }else{
2808 raw_printf(stderr, "Usage: .bail on|off\n");
2809 rc = 1;
2810 }
2811 }else
2812
2813 if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
@@ -2745,11 +2816,11 @@
2816 setBinaryMode(p->out);
2817 }else{
2818 setTextMode(p->out);
2819 }
2820 }else{
2821 raw_printf(stderr, "Usage: .binary on|off\n");
2822 rc = 1;
2823 }
2824 }else
2825
2826 /* The undocumented ".breakpoint" command causes a call to the no-op
@@ -2761,20 +2832,20 @@
2832
2833 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
2834 if( nArg==2 ){
2835 p->countChanges = booleanValue(azArg[1]);
2836 }else{
2837 raw_printf(stderr, "Usage: .changes on|off\n");
2838 rc = 1;
2839 }
2840 }else
2841
2842 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
2843 if( nArg==2 ){
2844 tryToClone(p, azArg[1]);
2845 }else{
2846 raw_printf(stderr, "Usage: .clone FILENAME\n");
2847 rc = 1;
2848 }
2849 }else
2850
2851 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
@@ -2788,11 +2859,11 @@
2859 data.colWidth[1] = 15;
2860 data.colWidth[2] = 58;
2861 data.cnt = 0;
2862 sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
2863 if( zErrMsg ){
2864 utf8_printf(stderr,"Error: %s\n", zErrMsg);
2865 sqlite3_free(zErrMsg);
2866 rc = 1;
2867 }
2868 }else
2869
@@ -2804,16 +2875,16 @@
2875 open_db(p, 0);
2876 /* When playing back a "dump", the content might appear in an order
2877 ** which causes immediate foreign key constraints to be violated.
2878 ** So disable foreign-key constraint enforcement to prevent problems. */
2879 if( nArg!=1 && nArg!=2 ){
2880 raw_printf(stderr, "Usage: .dump ?LIKE-PATTERN?\n");
2881 rc = 1;
2882 goto meta_command_exit;
2883 }
2884 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
2885 raw_printf(p->out, "BEGIN TRANSACTION;\n");
2886 p->writableSchema = 0;
2887 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
2888 p->nErr = 0;
2889 if( nArg==1 ){
2890 run_schema_dump_query(p,
@@ -2844,32 +2915,32 @@
2915 );
2916 zShellStatic = 0;
2917 }
2918 }
2919 if( p->writableSchema ){
2920 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
2921 p->writableSchema = 0;
2922 }
2923 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
2924 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
2925 raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
2926 }else
2927
2928 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
2929 if( nArg==2 ){
2930 p->echoOn = booleanValue(azArg[1]);
2931 }else{
2932 raw_printf(stderr, "Usage: .echo on|off\n");
2933 rc = 1;
2934 }
2935 }else
2936
2937 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
2938 if( nArg==2 ){
2939 p->autoEQP = booleanValue(azArg[1]);
2940 }else{
2941 raw_printf(stderr, "Usage: .eqp on|off\n");
2942 rc = 1;
2943 }
2944 }else
2945
2946 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
@@ -2915,11 +2986,11 @@
2986 if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
2987 ShellState data;
2988 char *zErrMsg = 0;
2989 int doStats = 0;
2990 if( nArg!=1 ){
2991 raw_printf(stderr, "Usage: .fullschema\n");
2992 rc = 1;
2993 goto meta_command_exit;
2994 }
2995 open_db(p, 0);
2996 memcpy(&data, p, sizeof(data));
@@ -2942,13 +3013,13 @@
3013 -1, &pStmt, 0);
3014 doStats = sqlite3_step(pStmt)==SQLITE_ROW;
3015 sqlite3_finalize(pStmt);
3016 }
3017 if( doStats==0 ){
3018 raw_printf(p->out, "/* No STAT tables available */\n");
3019 }else{
3020 raw_printf(p->out, "ANALYZE sqlite_master;\n");
3021 sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'",
3022 callback, &data, &zErrMsg);
3023 data.mode = MODE_Insert;
3024 data.zDestTable = "sqlite_stat1";
3025 shell_exec(p->db, "SELECT * FROM sqlite_stat1",
@@ -2957,25 +3028,25 @@
3028 shell_exec(p->db, "SELECT * FROM sqlite_stat3",
3029 shell_callback, &data,&zErrMsg);
3030 data.zDestTable = "sqlite_stat4";
3031 shell_exec(p->db, "SELECT * FROM sqlite_stat4",
3032 shell_callback, &data, &zErrMsg);
3033 raw_printf(p->out, "ANALYZE sqlite_master;\n");
3034 }
3035 }else
3036
3037 if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
3038 if( nArg==2 ){
3039 p->showHeader = booleanValue(azArg[1]);
3040 }else{
3041 raw_printf(stderr, "Usage: .headers on|off\n");
3042 rc = 1;
3043 }
3044 }else
3045
3046 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
3047 utf8_printf(p->out, "%s", zHelp);
3048 }else
3049
3050 if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
3051 char *zTable; /* Insert data into this table */
3052 char *zFile; /* Name of file to extra content from */
@@ -2989,31 +3060,32 @@
3060 ImportCtx sCtx; /* Reader context */
3061 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
3062 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close file */
3063
3064 if( nArg!=3 ){
3065 raw_printf(stderr, "Usage: .import FILE TABLE\n");
3066 goto meta_command_exit;
3067 }
3068 zFile = azArg[1];
3069 zTable = azArg[2];
3070 seenInterrupt = 0;
3071 memset(&sCtx, 0, sizeof(sCtx));
3072 open_db(p, 0);
3073 nSep = strlen30(p->colSeparator);
3074 if( nSep==0 ){
3075 raw_printf(stderr,
3076 "Error: non-null column separator required for import\n");
3077 return 1;
3078 }
3079 if( nSep>1 ){
3080 raw_printf(stderr, "Error: multi-character column separators not allowed"
3081 " for import\n");
3082 return 1;
3083 }
3084 nSep = strlen30(p->rowSeparator);
3085 if( nSep==0 ){
3086 raw_printf(stderr, "Error: non-null row separator required for import\n");
3087 return 1;
3088 }
3089 if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){
3090 /* When importing CSV (only), if the row separator is set to the
3091 ** default output row separator, change it to the default input
@@ -3021,19 +3093,19 @@
3093 ** and output row separators. */
3094 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
3095 nSep = strlen30(p->rowSeparator);
3096 }
3097 if( nSep>1 ){
3098 raw_printf(stderr, "Error: multi-character row separators not allowed"
3099 " for import\n");
3100 return 1;
3101 }
3102 sCtx.zFile = zFile;
3103 sCtx.nLine = 1;
3104 if( sCtx.zFile[0]=='|' ){
3105 #ifdef SQLITE_OMIT_POPEN
3106 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
3107 return 1;
3108 #else
3109 sCtx.in = popen(sCtx.zFile+1, "r");
3110 sCtx.zFile = "<pipe>";
3111 xCloser = pclose;
@@ -3046,18 +3118,18 @@
3118 xRead = ascii_read_one_field;
3119 }else{
3120 xRead = csv_read_one_field;
3121 }
3122 if( sCtx.in==0 ){
3123 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
3124 return 1;
3125 }
3126 sCtx.cColSep = p->colSeparator[0];
3127 sCtx.cRowSep = p->rowSeparator[0];
3128 zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
3129 if( zSql==0 ){
3130 raw_printf(stderr, "Error: out of memory\n");
3131 xCloser(sCtx.in);
3132 return 1;
3133 }
3134 nByte = strlen30(zSql);
3135 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
@@ -3072,18 +3144,18 @@
3144 }
3145 if( cSep=='(' ){
3146 sqlite3_free(zCreate);
3147 sqlite3_free(sCtx.z);
3148 xCloser(sCtx.in);
3149 utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
3150 return 1;
3151 }
3152 zCreate = sqlite3_mprintf("%z\n)", zCreate);
3153 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
3154 sqlite3_free(zCreate);
3155 if( rc ){
3156 utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
3157 sqlite3_errmsg(p->db));
3158 sqlite3_free(sCtx.z);
3159 xCloser(sCtx.in);
3160 return 1;
3161 }
@@ -3090,21 +3162,21 @@
3162 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3163 }
3164 sqlite3_free(zSql);
3165 if( rc ){
3166 if (pStmt) sqlite3_finalize(pStmt);
3167 utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
3168 xCloser(sCtx.in);
3169 return 1;
3170 }
3171 nCol = sqlite3_column_count(pStmt);
3172 sqlite3_finalize(pStmt);
3173 pStmt = 0;
3174 if( nCol==0 ) return 0; /* no columns, no error */
3175 zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
3176 if( zSql==0 ){
3177 raw_printf(stderr, "Error: out of memory\n");
3178 xCloser(sCtx.in);
3179 return 1;
3180 }
3181 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
3182 j = strlen30(zSql);
@@ -3115,11 +3187,11 @@
3187 zSql[j++] = ')';
3188 zSql[j] = 0;
3189 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3190 sqlite3_free(zSql);
3191 if( rc ){
3192 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
3193 if (pStmt) sqlite3_finalize(pStmt);
3194 xCloser(sCtx.in);
3195 return 1;
3196 }
3197 needCommit = sqlite3_get_autocommit(p->db);
@@ -3139,11 +3211,11 @@
3211 ** the remaining columns.
3212 */
3213 if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
3214 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
3215 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
3216 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
3217 "filling the rest with NULL\n",
3218 sCtx.zFile, startLine, nCol, i+1);
3219 i += 2;
3220 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
3221 }
@@ -3151,20 +3223,20 @@
3223 if( sCtx.cTerm==sCtx.cColSep ){
3224 do{
3225 xRead(&sCtx);
3226 i++;
3227 }while( sCtx.cTerm==sCtx.cColSep );
3228 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
3229 "extras ignored\n",
3230 sCtx.zFile, startLine, nCol, i);
3231 }
3232 if( i>=nCol ){
3233 sqlite3_step(pStmt);
3234 rc = sqlite3_reset(pStmt);
3235 if( rc!=SQLITE_OK ){
3236 utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
3237 startLine, sqlite3_errmsg(p->db));
3238 }
3239 }
3240 }while( sCtx.cTerm!=EOF );
3241
3242 xCloser(sCtx.in);
@@ -3202,20 +3274,21 @@
3274 "ORDER BY 1",
3275 callback, &data, &zErrMsg
3276 );
3277 zShellStatic = 0;
3278 }else{
3279 raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
3280 rc = 1;
3281 goto meta_command_exit;
3282 }
3283 if( zErrMsg ){
3284 utf8_printf(stderr,"Error: %s\n", zErrMsg);
3285 sqlite3_free(zErrMsg);
3286 rc = 1;
3287 }else if( rc != SQLITE_OK ){
3288 raw_printf(stderr,
3289 "Error: querying sqlite_master and sqlite_temp_master\n");
3290 rc = 1;
3291 }
3292 }else
3293
3294 #ifdef SQLITE_ENABLE_IOTRACE
@@ -3229,11 +3302,11 @@
3302 sqlite3IoTrace = iotracePrintf;
3303 iotrace = stdout;
3304 }else{
3305 iotrace = fopen(azArg[1], "w");
3306 if( iotrace==0 ){
3307 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
3308 sqlite3IoTrace = 0;
3309 rc = 1;
3310 }else{
3311 sqlite3IoTrace = iotracePrintf;
3312 }
@@ -3264,11 +3337,11 @@
3337 for(i=0; i<ArraySize(aLimit); i++){
3338 printf("%20s %d\n", aLimit[i].zLimitName,
3339 sqlite3_limit(p->db, aLimit[i].limitCode, -1));
3340 }
3341 }else if( nArg>3 ){
3342 raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
3343 rc = 1;
3344 goto meta_command_exit;
3345 }else{
3346 int iLimit = -1;
3347 n2 = strlen30(azArg[1]);
@@ -3275,18 +3348,18 @@
3348 for(i=0; i<ArraySize(aLimit); i++){
3349 if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
3350 if( iLimit<0 ){
3351 iLimit = i;
3352 }else{
3353 utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
3354 rc = 1;
3355 goto meta_command_exit;
3356 }
3357 }
3358 }
3359 if( iLimit<0 ){
3360 utf8_printf(stderr, "unknown limit: \"%s\"\n"
3361 "enter \".limits\" with no arguments for a list.\n",
3362 azArg[1]);
3363 rc = 1;
3364 goto meta_command_exit;
3365 }
@@ -3302,29 +3375,29 @@
3375 #ifndef SQLITE_OMIT_LOAD_EXTENSION
3376 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
3377 const char *zFile, *zProc;
3378 char *zErrMsg = 0;
3379 if( nArg<2 ){
3380 raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
3381 rc = 1;
3382 goto meta_command_exit;
3383 }
3384 zFile = azArg[1];
3385 zProc = nArg>=3 ? azArg[2] : 0;
3386 open_db(p, 0);
3387 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
3388 if( rc!=SQLITE_OK ){
3389 utf8_printf(stderr, "Error: %s\n", zErrMsg);
3390 sqlite3_free(zErrMsg);
3391 rc = 1;
3392 }
3393 }else
3394 #endif
3395
3396 if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
3397 if( nArg!=2 ){
3398 raw_printf(stderr, "Usage: .log FILENAME\n");
3399 rc = 1;
3400 }else{
3401 const char *zFile = azArg[1];
3402 output_file_close(p->pLog);
3403 p->pLog = output_file_open(zFile);
@@ -3359,11 +3432,11 @@
3432 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
3433 p->mode = MODE_Ascii;
3434 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
3435 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
3436 }else {
3437 raw_printf(stderr, "Error: mode should be one of: "
3438 "ascii column csv html insert line list tabs tcl\n");
3439 rc = 1;
3440 }
3441 }else
3442
@@ -3370,11 +3443,11 @@
3443 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
3444 if( nArg==2 ){
3445 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
3446 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
3447 }else{
3448 raw_printf(stderr, "Usage: .nullvalue STRING\n");
3449 rc = 1;
3450 }
3451 }else
3452
3453 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
@@ -3399,17 +3472,17 @@
3472 if( c=='o'
3473 && (strncmp(azArg[0], "output", n)==0 || strncmp(azArg[0], "once", n)==0)
3474 ){
3475 const char *zFile = nArg>=2 ? azArg[1] : "stdout";
3476 if( nArg>2 ){
3477 utf8_printf(stderr, "Usage: .%s FILE\n", azArg[0]);
3478 rc = 1;
3479 goto meta_command_exit;
3480 }
3481 if( n>1 && strncmp(azArg[0], "once", n)==0 ){
3482 if( nArg<2 ){
3483 raw_printf(stderr, "Usage: .once FILE\n");
3484 rc = 1;
3485 goto meta_command_exit;
3486 }
3487 p->outCount = 2;
3488 }else{
@@ -3416,17 +3489,17 @@
3489 p->outCount = 0;
3490 }
3491 output_reset(p);
3492 if( zFile[0]=='|' ){
3493 #ifdef SQLITE_OMIT_POPEN
3494 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
3495 rc = 1;
3496 p->out = stdout;
3497 #else
3498 p->out = popen(zFile + 1, "w");
3499 if( p->out==0 ){
3500 utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
3501 p->out = stdout;
3502 rc = 1;
3503 }else{
3504 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
3505 }
@@ -3433,11 +3506,11 @@
3506 #endif
3507 }else{
3508 p->out = output_file_open(zFile);
3509 if( p->out==0 ){
3510 if( strcmp(zFile,"off")!=0 ){
3511 utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
3512 }
3513 p->out = stdout;
3514 rc = 1;
3515 } else {
3516 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
@@ -3446,14 +3519,14 @@
3519 }else
3520
3521 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
3522 int i;
3523 for(i=1; i<nArg; i++){
3524 if( i>1 ) raw_printf(p->out, " ");
3525 utf8_printf(p->out, "%s", azArg[i]);
3526 }
3527 raw_printf(p->out, "\n");
3528 }else
3529
3530 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
3531 if( nArg >= 2) {
3532 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
@@ -3468,17 +3541,17 @@
3541 }else
3542
3543 if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
3544 FILE *alt;
3545 if( nArg!=2 ){
3546 raw_printf(stderr, "Usage: .read FILE\n");
3547 rc = 1;
3548 goto meta_command_exit;
3549 }
3550 alt = fopen(azArg[1], "rb");
3551 if( alt==0 ){
3552 utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
3553 rc = 1;
3554 }else{
3555 rc = process_input(p, alt);
3556 fclose(alt);
3557 }
@@ -3496,24 +3569,24 @@
3569 zDb = "main";
3570 }else if( nArg==3 ){
3571 zSrcFile = azArg[2];
3572 zDb = azArg[1];
3573 }else{
3574 raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
3575 rc = 1;
3576 goto meta_command_exit;
3577 }
3578 rc = sqlite3_open(zSrcFile, &pSrc);
3579 if( rc!=SQLITE_OK ){
3580 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
3581 sqlite3_close(pSrc);
3582 return 1;
3583 }
3584 open_db(p, 0);
3585 pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
3586 if( pBackup==0 ){
3587 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
3588 sqlite3_close(pSrc);
3589 return 1;
3590 }
3591 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
3592 || rc==SQLITE_BUSY ){
@@ -3524,14 +3597,14 @@
3597 }
3598 sqlite3_backup_finish(pBackup);
3599 if( rc==SQLITE_DONE ){
3600 rc = 0;
3601 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
3602 raw_printf(stderr, "Error: source database is busy\n");
3603 rc = 1;
3604 }else{
3605 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
3606 rc = 1;
3607 }
3608 sqlite3_close(pSrc);
3609 }else
3610
@@ -3538,14 +3611,14 @@
3611
3612 if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
3613 if( nArg==2 ){
3614 p->scanstatsOn = booleanValue(azArg[1]);
3615 #ifndef SQLITE_ENABLE_STMT_SCANSTATUS
3616 raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
3617 #endif
3618 }else{
3619 raw_printf(stderr, "Usage: .scanstats on|off\n");
3620 rc = 1;
3621 }
3622 }else
3623
3624 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
@@ -3608,20 +3681,20 @@
3681 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
3682 "ORDER BY rowid",
3683 callback, &data, &zErrMsg
3684 );
3685 }else{
3686 raw_printf(stderr, "Usage: .schema ?LIKE-PATTERN?\n");
3687 rc = 1;
3688 goto meta_command_exit;
3689 }
3690 if( zErrMsg ){
3691 utf8_printf(stderr,"Error: %s\n", zErrMsg);
3692 sqlite3_free(zErrMsg);
3693 rc = 1;
3694 }else if( rc != SQLITE_OK ){
3695 raw_printf(stderr,"Error: querying schema information\n");
3696 rc = 1;
3697 }else{
3698 rc = 0;
3699 }
3700 }else
@@ -3641,28 +3714,28 @@
3714 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
3715 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
3716 int i, v;
3717 for(i=1; i<nArg; i++){
3718 v = booleanValue(azArg[i]);
3719 utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
3720 }
3721 }
3722 if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
3723 int i; sqlite3_int64 v;
3724 for(i=1; i<nArg; i++){
3725 char zBuf[200];
3726 v = integerValue(azArg[i]);
3727 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
3728 utf8_printf(p->out, "%s", zBuf);
3729 }
3730 }
3731 }else
3732 #endif
3733
3734 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
3735 if( nArg<2 || nArg>3 ){
3736 raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
3737 rc = 1;
3738 }
3739 if( nArg>=2 ){
3740 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
3741 "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
@@ -3677,11 +3750,11 @@
3750 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
3751 ){
3752 char *zCmd;
3753 int i, x;
3754 if( nArg<2 ){
3755 raw_printf(stderr, "Usage: .system COMMAND\n");
3756 rc = 1;
3757 goto meta_command_exit;
3758 }
3759 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
3760 for(i=2; i<nArg; i++){
@@ -3688,49 +3761,49 @@
3761 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
3762 zCmd, azArg[i]);
3763 }
3764 x = system(zCmd);
3765 sqlite3_free(zCmd);
3766 if( x ) raw_printf(stderr, "System command returns %d\n", x);
3767 }else
3768
3769 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
3770 int i;
3771 if( nArg!=1 ){
3772 raw_printf(stderr, "Usage: .show\n");
3773 rc = 1;
3774 goto meta_command_exit;
3775 }
3776 utf8_printf(p->out, "%12.12s: %s\n","echo", p->echoOn ? "on" : "off");
3777 utf8_printf(p->out, "%12.12s: %s\n","eqp", p->autoEQP ? "on" : "off");
3778 utf8_printf(p->out,"%9.9s: %s\n","explain",p->normalMode.valid?"on":"off");
3779 utf8_printf(p->out,"%12.12s: %s\n","headers", p->showHeader ? "on" : "off");
3780 utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
3781 utf8_printf(p->out, "%12.12s: ", "nullvalue");
3782 output_c_string(p->out, p->nullValue);
3783 raw_printf(p->out, "\n");
3784 utf8_printf(p->out,"%12.12s: %s\n","output",
3785 strlen30(p->outfile) ? p->outfile : "stdout");
3786 utf8_printf(p->out,"%12.12s: ", "colseparator");
3787 output_c_string(p->out, p->colSeparator);
3788 raw_printf(p->out, "\n");
3789 utf8_printf(p->out,"%12.12s: ", "rowseparator");
3790 output_c_string(p->out, p->rowSeparator);
3791 raw_printf(p->out, "\n");
3792 utf8_printf(p->out, "%12.12s: %s\n","stats", p->statsOn ? "on" : "off");
3793 utf8_printf(p->out, "%12.12s: ", "width");
3794 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
3795 raw_printf(p->out, "%d ", p->colWidth[i]);
3796 }
3797 raw_printf(p->out, "\n");
3798 }else
3799
3800 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
3801 if( nArg==2 ){
3802 p->statsOn = booleanValue(azArg[1]);
3803 }else{
3804 raw_printf(stderr, "Usage: .stats on|off\n");
3805 rc = 1;
3806 }
3807 }else
3808
3809 if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
@@ -3824,13 +3897,14 @@
3897 if( nPrintCol<1 ) nPrintCol = 1;
3898 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
3899 for(i=0; i<nPrintRow; i++){
3900 for(j=i; j<nRow; j+=nPrintRow){
3901 char *zSp = j<nPrintRow ? "" : " ";
3902 utf8_printf(p->out, "%s%-*s", zSp, maxlen,
3903 azResult[j] ? azResult[j]:"");
3904 }
3905 raw_printf(p->out, "\n");
3906 }
3907 }
3908
3909 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
3910 sqlite3_free(azResult);
@@ -3869,31 +3943,31 @@
3943 for(i=0; i<ArraySize(aCtrl); i++){
3944 if( strncmp(azArg[1], aCtrl[i].zCtrlName, n2)==0 ){
3945 if( testctrl<0 ){
3946 testctrl = aCtrl[i].ctrlCode;
3947 }else{
3948 utf8_printf(stderr, "ambiguous option name: \"%s\"\n", azArg[1]);
3949 testctrl = -1;
3950 break;
3951 }
3952 }
3953 }
3954 if( testctrl<0 ) testctrl = (int)integerValue(azArg[1]);
3955 if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){
3956 utf8_printf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]);
3957 }else{
3958 switch(testctrl){
3959
3960 /* sqlite3_test_control(int, db, int) */
3961 case SQLITE_TESTCTRL_OPTIMIZATIONS:
3962 case SQLITE_TESTCTRL_RESERVE:
3963 if( nArg==3 ){
3964 int opt = (int)strtol(azArg[2], 0, 0);
3965 rc2 = sqlite3_test_control(testctrl, p->db, opt);
3966 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
3967 } else {
3968 utf8_printf(stderr,"Error: testctrl %s takes a single int option\n",
3969 azArg[1]);
3970 }
3971 break;
3972
3973 /* sqlite3_test_control(int) */
@@ -3901,24 +3975,25 @@
3975 case SQLITE_TESTCTRL_PRNG_RESTORE:
3976 case SQLITE_TESTCTRL_PRNG_RESET:
3977 case SQLITE_TESTCTRL_BYTEORDER:
3978 if( nArg==2 ){
3979 rc2 = sqlite3_test_control(testctrl);
3980 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
3981 } else {
3982 utf8_printf(stderr,"Error: testctrl %s takes no options\n",
3983 azArg[1]);
3984 }
3985 break;
3986
3987 /* sqlite3_test_control(int, uint) */
3988 case SQLITE_TESTCTRL_PENDING_BYTE:
3989 if( nArg==3 ){
3990 unsigned int opt = (unsigned int)integerValue(azArg[2]);
3991 rc2 = sqlite3_test_control(testctrl, opt);
3992 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
3993 } else {
3994 utf8_printf(stderr,"Error: testctrl %s takes a single unsigned"
3995 " int option\n", azArg[1]);
3996 }
3997 break;
3998
3999 /* sqlite3_test_control(int, int) */
@@ -3926,13 +4001,13 @@
4001 case SQLITE_TESTCTRL_ALWAYS:
4002 case SQLITE_TESTCTRL_NEVER_CORRUPT:
4003 if( nArg==3 ){
4004 int opt = booleanValue(azArg[2]);
4005 rc2 = sqlite3_test_control(testctrl, opt);
4006 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
4007 } else {
4008 utf8_printf(stderr,"Error: testctrl %s takes a single int option\n",
4009 azArg[1]);
4010 }
4011 break;
4012
4013 /* sqlite3_test_control(int, char *) */
@@ -3939,14 +4014,15 @@
4014 #ifdef SQLITE_N_KEYWORD
4015 case SQLITE_TESTCTRL_ISKEYWORD:
4016 if( nArg==3 ){
4017 const char *opt = azArg[2];
4018 rc2 = sqlite3_test_control(testctrl, opt);
4019 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
4020 } else {
4021 utf8_printf(stderr,
4022 "Error: testctrl %s takes a single char * option\n",
4023 azArg[1]);
4024 }
4025 break;
4026 #endif
4027
4028 case SQLITE_TESTCTRL_IMPOSTER:
@@ -3953,23 +4029,24 @@
4029 if( nArg==5 ){
4030 rc2 = sqlite3_test_control(testctrl, p->db,
4031 azArg[2],
4032 integerValue(azArg[3]),
4033 integerValue(azArg[4]));
4034 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
4035 }else{
4036 raw_printf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
4037 }
4038 break;
4039
4040 case SQLITE_TESTCTRL_BITVEC_TEST:
4041 case SQLITE_TESTCTRL_FAULT_INSTALL:
4042 case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
4043 case SQLITE_TESTCTRL_SCRATCHMALLOC:
4044 default:
4045 utf8_printf(stderr,
4046 "Error: CLI support for testctrl %s not implemented\n",
4047 azArg[1]);
4048 break;
4049 }
4050 }
4051 }else
4052
@@ -3980,23 +4057,23 @@
4057
4058 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
4059 if( nArg==2 ){
4060 enableTimer = booleanValue(azArg[1]);
4061 if( enableTimer && !HAS_TIMER ){
4062 raw_printf(stderr, "Error: timer not available on this system.\n");
4063 enableTimer = 0;
4064 }
4065 }else{
4066 raw_printf(stderr, "Usage: .timer on|off\n");
4067 rc = 1;
4068 }
4069 }else
4070
4071 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
4072 open_db(p, 0);
4073 if( nArg!=2 ){
4074 raw_printf(stderr, "Usage: .trace FILE|off\n");
4075 rc = 1;
4076 goto meta_command_exit;
4077 }
4078 output_file_close(p->traceOut);
4079 p->traceOut = output_file_open(azArg[1]);
@@ -4010,87 +4087,87 @@
4087 }else
4088
4089 #if SQLITE_USER_AUTHENTICATION
4090 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
4091 if( nArg<2 ){
4092 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
4093 rc = 1;
4094 goto meta_command_exit;
4095 }
4096 open_db(p, 0);
4097 if( strcmp(azArg[1],"login")==0 ){
4098 if( nArg!=4 ){
4099 raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
4100 rc = 1;
4101 goto meta_command_exit;
4102 }
4103 rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
4104 (int)strlen(azArg[3]));
4105 if( rc ){
4106 utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
4107 rc = 1;
4108 }
4109 }else if( strcmp(azArg[1],"add")==0 ){
4110 if( nArg!=5 ){
4111 raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
4112 rc = 1;
4113 goto meta_command_exit;
4114 }
4115 rc = sqlite3_user_add(p->db, azArg[2],
4116 azArg[3], (int)strlen(azArg[3]),
4117 booleanValue(azArg[4]));
4118 if( rc ){
4119 raw_printf(stderr, "User-Add failed: %d\n", rc);
4120 rc = 1;
4121 }
4122 }else if( strcmp(azArg[1],"edit")==0 ){
4123 if( nArg!=5 ){
4124 raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
4125 rc = 1;
4126 goto meta_command_exit;
4127 }
4128 rc = sqlite3_user_change(p->db, azArg[2],
4129 azArg[3], (int)strlen(azArg[3]),
4130 booleanValue(azArg[4]));
4131 if( rc ){
4132 raw_printf(stderr, "User-Edit failed: %d\n", rc);
4133 rc = 1;
4134 }
4135 }else if( strcmp(azArg[1],"delete")==0 ){
4136 if( nArg!=3 ){
4137 raw_printf(stderr, "Usage: .user delete USER\n");
4138 rc = 1;
4139 goto meta_command_exit;
4140 }
4141 rc = sqlite3_user_delete(p->db, azArg[2]);
4142 if( rc ){
4143 raw_printf(stderr, "User-Delete failed: %d\n", rc);
4144 rc = 1;
4145 }
4146 }else{
4147 raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
4148 rc = 1;
4149 goto meta_command_exit;
4150 }
4151 }else
4152 #endif /* SQLITE_USER_AUTHENTICATION */
4153
4154 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
4155 utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
4156 sqlite3_libversion(), sqlite3_sourceid());
4157 }else
4158
4159 if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
4160 const char *zDbName = nArg==2 ? azArg[1] : "main";
4161 sqlite3_vfs *pVfs;
4162 if( p->db ){
4163 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
4164 if( pVfs ){
4165 utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
4166 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
4167 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
4168 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
4169 }
4170 }
4171 }else
4172
4173 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
@@ -4097,11 +4174,11 @@
4174 const char *zDbName = nArg==2 ? azArg[1] : "main";
4175 char *zVfsName = 0;
4176 if( p->db ){
4177 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
4178 if( zVfsName ){
4179 utf8_printf(p->out, "%s\n", zVfsName);
4180 sqlite3_free(zVfsName);
4181 }
4182 }
4183 }else
4184
@@ -4119,11 +4196,11 @@
4196 p->colWidth[j-1] = (int)integerValue(azArg[j]);
4197 }
4198 }else
4199
4200 {
4201 utf8_printf(stderr, "Error: unknown command or invalid arguments: "
4202 " \"%s\". Enter \".help\" for help\n", azArg[0]);
4203 rc = 1;
4204 }
4205
4206 meta_command_exit:
@@ -4254,11 +4331,11 @@
4331 nLine = strlen30(zLine);
4332 if( nSql+nLine+2>=nAlloc ){
4333 nAlloc = nSql+nLine+100;
4334 zSql = realloc(zSql, nAlloc);
4335 if( zSql==0 ){
4336 raw_printf(stderr, "Error: out of memory\n");
4337 exit(1);
4338 }
4339 }
4340 nSqlPrior = nSql;
4341 if( nSql==0 ){
@@ -4288,19 +4365,19 @@
4365 "Error: near line %d:", startline);
4366 }else{
4367 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
4368 }
4369 if( zErrMsg!=0 ){
4370 utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
4371 sqlite3_free(zErrMsg);
4372 zErrMsg = 0;
4373 }else{
4374 utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
4375 }
4376 errCnt++;
4377 }else if( p->countChanges ){
4378 raw_printf(p->out, "changes: %3d total_changes: %d\n",
4379 sqlite3_changes(p->db), sqlite3_total_changes(p->db));
4380 }
4381 nSql = 0;
4382 if( p->outCount ){
4383 output_reset(p);
@@ -4311,11 +4388,11 @@
4388 nSql = 0;
4389 }
4390 }
4391 if( nSql ){
4392 if( !_all_whitespace(zSql) ){
4393 utf8_printf(stderr, "Error: incomplete SQL: %s\n", zSql);
4394 errCnt++;
4395 }
4396 }
4397 free(zSql);
4398 free(zLine);
@@ -4402,11 +4479,11 @@
4479 FILE *in = NULL;
4480
4481 if (sqliterc == NULL) {
4482 home_dir = find_home_dir();
4483 if( home_dir==0 ){
4484 raw_printf(stderr, "-- warning: cannot find home directory;"
4485 " cannot read ~/.sqliterc\n");
4486 return;
4487 }
4488 sqlite3_initialize();
4489 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
@@ -4413,11 +4490,11 @@
4490 sqliterc = zBuf;
4491 }
4492 in = fopen(sqliterc,"rb");
4493 if( in ){
4494 if( stdin_is_interactive ){
4495 utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
4496 }
4497 process_input(p,in);
4498 fclose(in);
4499 }
4500 sqlite3_free(zBuf);
@@ -4460,18 +4537,18 @@
4537 #ifdef SQLITE_ENABLE_VFSTRACE
4538 " -vfstrace enable tracing of all VFS calls\n"
4539 #endif
4540 ;
4541 static void usage(int showDetail){
4542 utf8_printf(stderr,
4543 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
4544 "FILENAME is the name of an SQLite database. A new database is created\n"
4545 "if the file does not previously exist.\n", Argv0);
4546 if( showDetail ){
4547 utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
4548 }else{
4549 raw_printf(stderr, "Use the -help option for additional information\n");
4550 }
4551 exit(1);
4552 }
4553
4554 /*
@@ -4515,11 +4592,11 @@
4592 ** Get the argument to an --option. Throw an error and die if no argument
4593 ** is available.
4594 */
4595 static char *cmdline_option_value(int argc, char **argv, int i){
4596 if( i==argc ){
4597 utf8_printf(stderr, "%s: Error: missing argument to %s\n",
4598 argv[0], argv[argc-1]);
4599 exit(1);
4600 }
4601 return argv[i];
4602 }
@@ -4535,20 +4612,21 @@
4612 int nCmd = 0;
4613 char **azCmd = 0;
4614
4615 #if USE_SYSTEM_SQLITE+0!=1
4616 if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
4617 utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
4618 sqlite3_sourceid(), SQLITE_SOURCE_ID);
4619 exit(1);
4620 }
4621 #endif
4622 setBinaryMode(stdin);
4623 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
4624 Argv0 = argv[0];
4625 main_init(&data);
4626 stdin_is_interactive = isatty(0);
4627 stdout_is_console = isatty(1);
4628
4629 /* Make sure we have a valid signal handler early, before anything
4630 ** else is done.
4631 */
4632 #ifdef SIGINT
@@ -4583,11 +4661,11 @@
4661 ** mean that nothing is read from stdin */
4662 readStdin = 0;
4663 nCmd++;
4664 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
4665 if( azCmd==0 ){
4666 raw_printf(stderr, "out of memory\n");
4667 exit(1);
4668 }
4669 azCmd[nCmd-1] = z;
4670 }
4671 }
@@ -4665,21 +4743,21 @@
4743 }else if( strcmp(z,"-vfs")==0 ){
4744 sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i));
4745 if( pVfs ){
4746 sqlite3_vfs_register(pVfs, 1);
4747 }else{
4748 utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
4749 exit(1);
4750 }
4751 }
4752 }
4753 if( data.zDbFilename==0 ){
4754 #ifndef SQLITE_OMIT_MEMORYDB
4755 data.zDbFilename = ":memory:";
4756 warnInmemoryDb = argc==1;
4757 #else
4758 utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
4759 return 1;
4760 #endif
4761 }
4762 data.out = stdout;
4763
@@ -4797,20 +4875,20 @@
4875 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
4876 }else{
4877 open_db(&data, 0);
4878 rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg);
4879 if( zErrMsg!=0 ){
4880 utf8_printf(stderr,"Error: %s\n", zErrMsg);
4881 if( bail_on_error ) return rc!=0 ? rc : 1;
4882 }else if( rc!=0 ){
4883 utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
4884 if( bail_on_error ) return rc;
4885 }
4886 }
4887 }else{
4888 utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
4889 raw_printf(stderr,"Use -help for a list of options.\n");
4890 return 1;
4891 }
4892 }
4893
4894 if( !readStdin ){
@@ -4824,14 +4902,14 @@
4902 if( rc ) return rc==2 ? 0 : rc;
4903 }else{
4904 open_db(&data, 0);
4905 rc = shell_exec(data.db, azCmd[i], shell_callback, &data, &zErrMsg);
4906 if( zErrMsg!=0 ){
4907 utf8_printf(stderr,"Error: %s\n", zErrMsg);
4908 return rc!=0 ? rc : 1;
4909 }else if( rc!=0 ){
4910 utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
4911 return rc;
4912 }
4913 }
4914 }
4915 free(azCmd);
4916
+220 -112
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -325,11 +325,11 @@
325325
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
326326
** [sqlite_version()] and [sqlite_source_id()].
327327
*/
328328
#define SQLITE_VERSION "3.10.0"
329329
#define SQLITE_VERSION_NUMBER 3010000
330
-#define SQLITE_SOURCE_ID "2015-12-23 10:54:48 b910a3d53769689d9212a06f974ccce54844bbe4"
330
+#define SQLITE_SOURCE_ID "2016-01-06 11:01:07 fd0a50f0797d154fefff724624f00548b5320566"
331331
332332
/*
333333
** CAPI3REF: Run-Time Library Version Numbers
334334
** KEYWORDS: sqlite3_version, sqlite3_sourceid
335335
**
@@ -9901,15 +9901,10 @@
99019901
** For best performance, an attempt is made to guess at the byte-order
99029902
** using C-preprocessor macros. If that is unsuccessful, or if
99039903
** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
99049904
** at run-time.
99059905
*/
9906
-#ifdef SQLITE_AMALGAMATION
9907
-SQLITE_PRIVATE const int sqlite3one = 1;
9908
-#else
9909
-SQLITE_PRIVATE const int sqlite3one;
9910
-#endif
99119906
#if (defined(i386) || defined(__i386__) || defined(_M_IX86) || \
99129907
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
99139908
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
99149909
defined(__arm__)) && !defined(SQLITE_RUNTIME_BYTEORDER)
99159910
# define SQLITE_BYTEORDER 1234
@@ -9923,10 +9918,15 @@
99239918
# define SQLITE_BIGENDIAN 1
99249919
# define SQLITE_LITTLEENDIAN 0
99259920
# define SQLITE_UTF16NATIVE SQLITE_UTF16BE
99269921
#endif
99279922
#if !defined(SQLITE_BYTEORDER)
9923
+# ifdef SQLITE_AMALGAMATION
9924
+ const int sqlite3one = 1;
9925
+# else
9926
+ extern const int sqlite3one;
9927
+# endif
99289928
# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */
99299929
# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
99309930
# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
99319931
# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
99329932
#endif
@@ -12317,11 +12317,11 @@
1231712317
char *zDflt; /* Original text of the default value */
1231812318
char *zType; /* Data type for this column */
1231912319
char *zColl; /* Collating sequence. If NULL, use the default */
1232012320
u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
1232112321
char affinity; /* One of the SQLITE_AFF_... values */
12322
- u8 szEst; /* Estimated size of this column. INT==1 */
12322
+ u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */
1232312323
u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */
1232412324
};
1232512325
1232612326
/* Allowed values for Column.colFlags:
1232712327
*/
@@ -12727,11 +12727,11 @@
1272712727
Table *pTable; /* The SQL table being indexed */
1272812728
char *zColAff; /* String defining the affinity of each column */
1272912729
Index *pNext; /* The next index associated with the same table */
1273012730
Schema *pSchema; /* Schema containing this index */
1273112731
u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
12732
- char **azColl; /* Array of collation sequence names for index */
12732
+ const char **azColl; /* Array of collation sequence names for index */
1273312733
Expr *pPartIdxWhere; /* WHERE clause for partial indices */
1273412734
ExprList *aColExpr; /* Column expressions */
1273512735
int tnum; /* DB Page containing root of this index */
1273612736
LogEst szIdxRow; /* Estimated average row size in bytes */
1273712737
u16 nKeyCol; /* Number of columns forming the key */
@@ -13527,10 +13527,11 @@
1352713527
int nTab; /* Number of previously allocated VDBE cursors */
1352813528
int nMem; /* Number of memory cells used so far */
1352913529
int nSet; /* Number of sets used so far */
1353013530
int nOnce; /* Number of OP_Once instructions so far */
1353113531
int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
13532
+ int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
1353213533
int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */
1353313534
int ckBase; /* Base register of data during check constraints */
1353413535
int iSelfTab; /* Table of an index whose exprs are being coded */
1353513536
int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
1353613537
int iCacheCnt; /* Counter used to generate aColCache[].lru values */
@@ -13758,13 +13759,13 @@
1375813759
*/
1375913760
struct StrAccum {
1376013761
sqlite3 *db; /* Optional database for lookaside. Can be NULL */
1376113762
char *zBase; /* A base allocation. Not from malloc. */
1376213763
char *zText; /* The string collected so far */
13763
- int nChar; /* Length of the string so far */
13764
- int nAlloc; /* Amount of space allocated in zText */
13765
- int mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */
13764
+ u32 nChar; /* Length of the string so far */
13765
+ u32 nAlloc; /* Amount of space allocated in zText */
13766
+ u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */
1376613767
u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
1376713768
u8 bMalloced; /* zText points to allocated space */
1376813769
};
1376913770
#define STRACCUM_NOMEM 1
1377013771
#define STRACCUM_TOOBIG 2
@@ -14143,11 +14144,15 @@
1414314144
SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
1414414145
SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
1414514146
SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*);
1414614147
SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index*, i16);
1414714148
SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
14148
-SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*);
14149
+#if SQLITE_ENABLE_HIDDEN_COLUMNS
14150
+SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*);
14151
+#else
14152
+# define sqlite3ColumnPropertiesFromName(T,C) /* no-op */
14153
+#endif
1414914154
SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*);
1415014155
SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
1415114156
SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
1415214157
SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
1415314158
SQLITE_PRIVATE void sqlite3AddColumnType(Parse*,Token*);
@@ -14494,10 +14499,11 @@
1449414499
SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
1449514500
SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
1449614501
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
1449714502
#ifndef SQLITE_AMALGAMATION
1449814503
SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[];
14504
+SQLITE_PRIVATE const char sqlite3StrBINARY[];
1449914505
SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
1450014506
SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[];
1450114507
SQLITE_PRIVATE const Token sqlite3IntTokens[];
1450214508
SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config;
1450314509
SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
@@ -15099,10 +15105,15 @@
1509915105
** from the comments following the "case OP_xxxx:" statements in
1510015106
** the vdbe.c file.
1510115107
*/
1510215108
SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
1510315109
15110
+/*
15111
+** Name of the default collating sequence
15112
+*/
15113
+SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY";
15114
+
1510415115
/************** End of global.c **********************************************/
1510515116
/************** Begin file ctime.c *******************************************/
1510615117
/*
1510715118
** 2010 February 23
1510815119
**
@@ -20655,10 +20666,12 @@
2065520666
int trace; /* True to trace changes */
2065620667
#endif
2065720668
};
2065820669
#if SQLITE_MUTEX_NREF
2065920670
#define SQLITE3_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,0,0,(pthread_t)0,0}
20671
+#elif defined(SQLITE_ENABLE_API_ARMOR)
20672
+#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0 }
2066020673
#else
2066120674
#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
2066220675
#endif
2066320676
2066420677
/*
@@ -24490,17 +24503,17 @@
2449024503
*/
2449124504
/* #include "sqliteInt.h" */
2449224505
/* #include <assert.h> */
2449324506
/* #include "vdbeInt.h" */
2449424507
24495
-#ifndef SQLITE_AMALGAMATION
24508
+#if !defined(SQLITE_AMALGAMATION) && SQLITE_BYTEORDER==0
2449624509
/*
2449724510
** The following constant value is used by the SQLITE_BIGENDIAN and
2449824511
** SQLITE_LITTLEENDIAN macros.
2449924512
*/
2450024513
SQLITE_PRIVATE const int sqlite3one = 1;
24501
-#endif /* SQLITE_AMALGAMATION */
24514
+#endif /* SQLITE_AMALGAMATION && SQLITE_BYTEORDER==0 */
2450224515
2450324516
/*
2450424517
** This lookup table is used to help decode the first byte of
2450524518
** a multi-byte UTF8 character.
2450624519
*/
@@ -54549,11 +54562,10 @@
5454954562
struct CellInfo {
5455054563
i64 nKey; /* The key for INTKEY tables, or nPayload otherwise */
5455154564
u8 *pPayload; /* Pointer to the start of payload */
5455254565
u32 nPayload; /* Bytes of payload */
5455354566
u16 nLocal; /* Amount of payload held locally, not on overflow */
54554
- u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */
5455554567
u16 nSize; /* Size of the cell content on the main b-tree page */
5455654568
};
5455754569
5455854570
/*
5455954571
** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than
@@ -56130,12 +56142,11 @@
5613056142
if( surplus <= maxLocal ){
5613156143
pInfo->nLocal = (u16)surplus;
5613256144
}else{
5613356145
pInfo->nLocal = (u16)minLocal;
5613456146
}
56135
- pInfo->iOverflow = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell);
56136
- pInfo->nSize = pInfo->iOverflow + 4;
56147
+ pInfo->nSize = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell) + 4;
5613756148
}
5613856149
5613956150
/*
5614056151
** The following routines are implementations of the MemPage.xParseCell()
5614156152
** method.
@@ -56163,11 +56174,10 @@
5616356174
UNUSED_PARAMETER(pPage);
5616456175
#endif
5616556176
pInfo->nSize = 4 + getVarint(&pCell[4], (u64*)&pInfo->nKey);
5616656177
pInfo->nPayload = 0;
5616756178
pInfo->nLocal = 0;
56168
- pInfo->iOverflow = 0;
5616956179
pInfo->pPayload = 0;
5617056180
return;
5617156181
}
5617256182
static void btreeParseCellPtr(
5617356183
MemPage *pPage, /* Page containing the cell */
@@ -56233,11 +56243,10 @@
5623356243
** on the local page. No overflow is required.
5623456244
*/
5623556245
pInfo->nSize = nPayload + (u16)(pIter - pCell);
5623656246
if( pInfo->nSize<4 ) pInfo->nSize = 4;
5623756247
pInfo->nLocal = (u16)nPayload;
56238
- pInfo->iOverflow = 0;
5623956248
}else{
5624056249
btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo);
5624156250
}
5624256251
}
5624356252
static void btreeParseCellPtrIndex(
@@ -56272,11 +56281,10 @@
5627256281
** on the local page. No overflow is required.
5627356282
*/
5627456283
pInfo->nSize = nPayload + (u16)(pIter - pCell);
5627556284
if( pInfo->nSize<4 ) pInfo->nSize = 4;
5627656285
pInfo->nLocal = (u16)nPayload;
56277
- pInfo->iOverflow = 0;
5627856286
}else{
5627956287
btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo);
5628056288
}
5628156289
}
5628256290
static void btreeParseCell(
@@ -56388,12 +56396,12 @@
5638856396
static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
5638956397
CellInfo info;
5639056398
if( *pRC ) return;
5639156399
assert( pCell!=0 );
5639256400
pPage->xParseCell(pPage, pCell, &info);
56393
- if( info.iOverflow ){
56394
- Pgno ovfl = get4byte(&pCell[info.iOverflow]);
56401
+ if( info.nLocal<info.nPayload ){
56402
+ Pgno ovfl = get4byte(&pCell[info.nSize-4]);
5639556403
ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC);
5639656404
}
5639756405
}
5639856406
#endif
5639956407
@@ -58427,15 +58435,15 @@
5842758435
for(i=0; i<nCell; i++){
5842858436
u8 *pCell = findCell(pPage, i);
5842958437
if( eType==PTRMAP_OVERFLOW1 ){
5843058438
CellInfo info;
5843158439
pPage->xParseCell(pPage, pCell, &info);
58432
- if( info.iOverflow
58433
- && pCell+info.iOverflow+3<=pPage->aData+pPage->maskPage
58434
- && iFrom==get4byte(&pCell[info.iOverflow])
58440
+ if( info.nLocal<info.nPayload
58441
+ && pCell+info.nSize-1<=pPage->aData+pPage->maskPage
58442
+ && iFrom==get4byte(pCell+info.nSize-4)
5843558443
){
58436
- put4byte(&pCell[info.iOverflow], iTo);
58444
+ put4byte(pCell+info.nSize-4, iTo);
5843758445
break;
5843858446
}
5843958447
}else{
5844058448
if( get4byte(pCell)==iFrom ){
5844158449
put4byte(pCell, iTo);
@@ -61073,17 +61081,17 @@
6107361081
u32 ovflPageSize;
6107461082
6107561083
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
6107661084
pPage->xParseCell(pPage, pCell, &info);
6107761085
*pnSize = info.nSize;
61078
- if( info.iOverflow==0 ){
61086
+ if( info.nLocal==info.nPayload ){
6107961087
return SQLITE_OK; /* No overflow pages. Return without doing anything */
6108061088
}
61081
- if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){
61089
+ if( pCell+info.nSize-1 > pPage->aData+pPage->maskPage ){
6108261090
return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */
6108361091
}
61084
- ovflPgno = get4byte(&pCell[info.iOverflow]);
61092
+ ovflPgno = get4byte(pCell + info.nSize - 4);
6108561093
assert( pBt->usableSize > 4 );
6108661094
ovflPageSize = pBt->usableSize - 4;
6108761095
nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
6108861096
assert( nOvfl>0 ||
6108961097
(CORRUPT_DB && (info.nPayload + ovflPageSize)<ovflPageSize)
@@ -61228,11 +61236,10 @@
6122861236
pPage->xParseCell(pPage, pCell, &info);
6122961237
assert( nHeader=(int)(info.pPayload - pCell) );
6123061238
assert( info.nKey==nKey );
6123161239
assert( *pnSize == info.nSize );
6123261240
assert( spaceLeft == info.nLocal );
61233
- assert( pPrior == &pCell[info.iOverflow] );
6123461241
}
6123561242
#endif
6123661243
6123761244
/* Write the payload into the local Cell and any extra into overflow pages */
6123861245
while( nPayload>0 ){
@@ -61938,12 +61945,12 @@
6193861945
CellInfo info;
6193961946
u8 *z;
6194061947
6194161948
z = findCell(pPage, j);
6194261949
pPage->xParseCell(pPage, z, &info);
61943
- if( info.iOverflow ){
61944
- Pgno ovfl = get4byte(&z[info.iOverflow]);
61950
+ if( info.nLocal<info.nPayload ){
61951
+ Pgno ovfl = get4byte(&z[info.nSize-4]);
6194561952
ptrmapGet(pBt, ovfl, &e, &n);
6194661953
assert( n==pPage->pgno && e==PTRMAP_OVERFLOW1 );
6194761954
}
6194861955
if( !pPage->leaf ){
6194961956
Pgno child = get4byte(z);
@@ -63305,11 +63312,11 @@
6330563312
rc = balance(pCur);
6330663313
}
6330763314
6330863315
if( rc==SQLITE_OK ){
6330963316
if( bSkipnext ){
63310
- assert( bPreserve && pCur->iPage==iCellDepth );
63317
+ assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) );
6331163318
assert( pPage==pCur->apPage[pCur->iPage] );
6331263319
assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell );
6331363320
pCur->eState = CURSOR_SKIPNEXT;
6331463321
if( iCellIdx>=pPage->nCell ){
6331563322
pCur->skipNext = -1;
@@ -64245,13 +64252,13 @@
6424564252
6424664253
/* Check the content overflow list */
6424764254
if( info.nPayload>info.nLocal ){
6424864255
int nPage; /* Number of pages on the overflow chain */
6424964256
Pgno pgnoOvfl; /* First page of the overflow chain */
64250
- assert( pc + info.iOverflow <= usableSize );
64257
+ assert( pc + info.nSize - 4 <= usableSize );
6425164258
nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
64252
- pgnoOvfl = get4byte(&pCell[info.iOverflow]);
64259
+ pgnoOvfl = get4byte(&pCell[info.nSize - 4]);
6425364260
#ifndef SQLITE_OMIT_AUTOVACUUM
6425464261
if( pBt->autoVacuum ){
6425564262
checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage);
6425664263
}
6425764264
#endif
@@ -67316,10 +67323,11 @@
6731667323
p->magic = VDBE_MAGIC_INIT;
6731767324
p->pParse = pParse;
6731867325
assert( pParse->aLabel==0 );
6731967326
assert( pParse->nLabel==0 );
6732067327
assert( pParse->nOpAlloc==0 );
67328
+ assert( pParse->szOpAlloc==0 );
6732167329
return p;
6732267330
}
6732367331
6732467332
/*
6732567333
** Change the error string stored in Vdbe.zErrMsg
@@ -67405,11 +67413,12 @@
6740567413
6740667414
assert( nOp<=(1024/sizeof(Op)) );
6740767415
assert( nNew>=(p->nOpAlloc+nOp) );
6740867416
pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
6740967417
if( pNew ){
67410
- p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op);
67418
+ p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew);
67419
+ p->nOpAlloc = p->szOpAlloc/sizeof(Op);
6741167420
v->aOp = pNew;
6741267421
}
6741367422
return (pNew ? SQLITE_OK : SQLITE_NOMEM);
6741467423
}
6741567424
@@ -69127,24 +69136,31 @@
6912769136
**
6912869137
** See also: allocateCursor().
6912969138
*/
6913069139
nMem += nCursor;
6913169140
69132
- /* Allocate space for memory registers, SQL variables, VDBE cursors and
69133
- ** an array to marshal SQL function arguments in.
69141
+ /* zCsr will initially point to nFree bytes of unused space at the
69142
+ ** end of the opcode array, p->aOp. The computation of nFree is
69143
+ ** conservative - it might be smaller than the true number of free
69144
+ ** bytes, but never larger. nFree must be a multiple of 8 - it is
69145
+ ** rounded down if is not.
6913469146
*/
69135
- zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */
69136
- assert( pParse->nOpAlloc*sizeof(Op) <= 0x7fffff00 );
69137
- nFree = (pParse->nOpAlloc - p->nOp)*sizeof(p->aOp[0]); /* Available space */
69147
+ n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode space used */
69148
+ zCsr = &((u8*)p->aOp)[n]; /* Unused opcode space */
69149
+ assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
69150
+ nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused space */
69151
+ assert( nFree>=0 );
69152
+ if( nFree>0 ){
69153
+ memset(zCsr, 0, nFree);
69154
+ assert( EIGHT_BYTE_ALIGNMENT(&zCsr[nFree]) );
69155
+ }
6913869156
6913969157
resolveP2Values(p, &nArg);
6914069158
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
6914169159
if( pParse->explain && nMem<10 ){
6914269160
nMem = 10;
6914369161
}
69144
- memset(zCsr, 0, nFree);
69145
- assert( EIGHT_BYTE_ALIGNMENT(&zCsr[nFree]) );
6914669162
p->expired = 0;
6914769163
6914869164
/* Memory for registers, parameters, cursor, etc, is allocated in two
6914969165
** passes. On the first pass, we try to reuse unused space at the
6915069166
** end of the opcode array. If we are unable to satisfy all memory
@@ -71029,11 +71045,11 @@
7102971045
}
7103071046
if( (f2 & MEM_Str)==0 ){
7103171047
return -1;
7103271048
}
7103371049
71034
- assert( pMem1->enc==pMem2->enc );
71050
+ assert( pMem1->enc==pMem2->enc || pMem1->db->mallocFailed );
7103571051
assert( pMem1->enc==SQLITE_UTF8 ||
7103671052
pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
7103771053
7103871054
/* The collation sequence must be defined at this point, even if
7103971055
** the user deletes the collation sequence after the vdbe program is
@@ -75665,42 +75681,41 @@
7566575681
}
7566675682
}else{
7566775683
/* Neither operand is NULL. Do a comparison. */
7566875684
affinity = pOp->p5 & SQLITE_AFF_MASK;
7566975685
if( affinity>=SQLITE_AFF_NUMERIC ){
75670
- if( (pIn1->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
75686
+ if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
7567175687
applyNumericAffinity(pIn1,0);
7567275688
}
75673
- if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
75689
+ if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
7567475690
applyNumericAffinity(pIn3,0);
7567575691
}
7567675692
}else if( affinity==SQLITE_AFF_TEXT ){
75677
- if( (pIn1->flags & MEM_Str)==0 && (pIn1->flags & (MEM_Int|MEM_Real))!=0 ){
75693
+ if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){
7567875694
testcase( pIn1->flags & MEM_Int );
7567975695
testcase( pIn1->flags & MEM_Real );
7568075696
sqlite3VdbeMemStringify(pIn1, encoding, 1);
7568175697
testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
7568275698
flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
7568375699
}
75684
- if( (pIn3->flags & MEM_Str)==0 && (pIn3->flags & (MEM_Int|MEM_Real))!=0 ){
75700
+ if( (flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0 ){
7568575701
testcase( pIn3->flags & MEM_Int );
7568675702
testcase( pIn3->flags & MEM_Real );
7568775703
sqlite3VdbeMemStringify(pIn3, encoding, 1);
7568875704
testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
7568975705
flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
7569075706
}
7569175707
}
7569275708
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
75693
- if( pIn1->flags & MEM_Zero ){
75709
+ if( flags1 & MEM_Zero ){
7569475710
sqlite3VdbeMemExpandBlob(pIn1);
7569575711
flags1 &= ~MEM_Zero;
7569675712
}
75697
- if( pIn3->flags & MEM_Zero ){
75713
+ if( flags3 & MEM_Zero ){
7569875714
sqlite3VdbeMemExpandBlob(pIn3);
7569975715
flags3 &= ~MEM_Zero;
7570075716
}
75701
- if( db->mallocFailed ) goto no_mem;
7570275717
res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
7570375718
}
7570475719
switch( pOp->opcode ){
7570575720
case OP_Eq: res = res==0; break;
7570675721
case OP_Ne: res = res!=0; break;
@@ -76194,11 +76209,11 @@
7619476209
){
7619576210
rc = SQLITE_CORRUPT_BKPT;
7619676211
goto op_column_error;
7619776212
}
7619876213
}else{
76199
- VVA_ONLY( t = 0; ) /* Only needed by assert() statements */
76214
+ t = 0;
7620076215
}
7620176216
7620276217
/* If after trying to extract new entries from the header, nHdrParsed is
7620376218
** still not up to p2, that means that the record has fewer than p2
7620476219
** columns. So the result will be either the default value or a NULL.
@@ -77072,11 +77087,11 @@
7707277087
7707377088
open_cursor_set_hints:
7707477089
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
7707577090
assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
7707677091
testcase( pOp->p5 & OPFLAG_BULKCSR );
77077
-#ifdef SQLITE_ENABLE_CURSOR_HINT
77092
+#ifdef SQLITE_ENABLE_CURSOR_HINTS
7707877093
testcase( pOp->p2 & OPFLAG_SEEKEQ );
7707977094
#endif
7708077095
sqlite3BtreeCursorHintFlags(pCur->uc.pCursor,
7708177096
(pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
7708277097
break;
@@ -86739,11 +86754,11 @@
8673986754
}
8674086755
if( isReduced ){
8674186756
assert( ExprHasProperty(p, EP_Reduced)==0 );
8674286757
memcpy(zAlloc, p, nNewSize);
8674386758
}else{
86744
- int nSize = exprStructSize(p);
86759
+ u32 nSize = (u32)exprStructSize(p);
8674586760
memcpy(zAlloc, p, nSize);
8674686761
if( nSize<EXPR_FULLSIZE ){
8674786762
memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
8674886763
}
8674986764
}
@@ -94128,11 +94143,11 @@
9412894143
sqlite3DeleteIndexSamples(db, p);
9412994144
#endif
9413094145
sqlite3ExprDelete(db, p->pPartIdxWhere);
9413194146
sqlite3ExprListDelete(db, p->aColExpr);
9413294147
sqlite3DbFree(db, p->zColAff);
94133
- if( p->isResized ) sqlite3DbFree(db, p->azColl);
94148
+ if( p->isResized ) sqlite3DbFree(db, (void *)p->azColl);
9413494149
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
9413594150
sqlite3_free(p->aiRowEst);
9413694151
#endif
9413794152
sqlite3DbFree(db, p);
9413894153
}
@@ -94731,19 +94746,19 @@
9473194746
}
9473294747
9473394748
/* Set properties of a table column based on the (magical)
9473494749
** name of the column.
9473594750
*/
94736
-SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
9473794751
#if SQLITE_ENABLE_HIDDEN_COLUMNS
94752
+SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
9473894753
if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){
9473994754
pCol->colFlags |= COLFLAG_HIDDEN;
9474094755
}else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){
9474194756
pTab->tabFlags |= TF_OOOHidden;
9474294757
}
94758
+}
9474394759
#endif
94744
-}
9474594760
9474694761
9474794762
/*
9474894763
** Add a new column to the table currently being constructed.
9474994764
**
@@ -95319,11 +95334,11 @@
9531995334
assert( pIdx->isResized==0 );
9532095335
nByte = (sizeof(char*) + sizeof(i16) + 1)*N;
9532195336
zExtra = sqlite3DbMallocZero(db, nByte);
9532295337
if( zExtra==0 ) return SQLITE_NOMEM;
9532395338
memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
95324
- pIdx->azColl = (char**)zExtra;
95339
+ pIdx->azColl = (const char**)zExtra;
9532595340
zExtra += sizeof(char*)*N;
9532695341
memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn);
9532795342
pIdx->aiColumn = (i16*)zExtra;
9532895343
zExtra += sizeof(i16)*N;
9532995344
memcpy(zExtra, pIdx->aSortOrder, pIdx->nColumn);
@@ -95458,11 +95473,11 @@
9545895473
9545995474
/* Make sure every column of the PRIMARY KEY is NOT NULL. (Except,
9546095475
** do not enforce this for imposter tables.) */
9546195476
if( !db->init.imposterTable ){
9546295477
for(i=0; i<nPk; i++){
95463
- pTab->aCol[pPk->aiColumn[i]].notNull = 1;
95478
+ pTab->aCol[pPk->aiColumn[i]].notNull = OE_Abort;
9546495479
}
9546595480
pPk->uniqNotNull = 1;
9546695481
}
9546795482
9546895483
/* The root page of the PRIMARY KEY is the table root page */
@@ -95500,11 +95515,11 @@
9550095515
if( resizeIndexObject(db, pPk, pTab->nCol) ) return;
9550195516
for(i=0, j=nPk; i<pTab->nCol; i++){
9550295517
if( !hasColumn(pPk->aiColumn, j, i) ){
9550395518
assert( j<pPk->nColumn );
9550495519
pPk->aiColumn[j] = i;
95505
- pPk->azColl[j] = "BINARY";
95520
+ pPk->azColl[j] = sqlite3StrBINARY;
9550695521
j++;
9550795522
}
9550895523
}
9550995524
assert( pPk->nColumn==j );
9551095525
assert( pTab->nCol==j );
@@ -96550,11 +96565,11 @@
9655096565
sizeof(i16)*nCol + /* Index.aiColumn */
9655196566
sizeof(u8)*nCol); /* Index.aSortOrder */
9655296567
p = sqlite3DbMallocZero(db, nByte + nExtra);
9655396568
if( p ){
9655496569
char *pExtra = ((char*)p)+ROUND8(sizeof(Index));
96555
- p->azColl = (char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol);
96570
+ p->azColl = (const char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol);
9655696571
p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1);
9655796572
p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol;
9655896573
p->aSortOrder = (u8*)pExtra;
9655996574
p->nColumn = nCol;
9656096575
p->nKeyCol = nCol - 1;
@@ -96827,11 +96842,11 @@
9682796842
** index key.
9682896843
*/
9682996844
for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
9683096845
Expr *pCExpr; /* The i-th index expression */
9683196846
int requestedSortOrder; /* ASC or DESC on the i-th expression */
96832
- char *zColl; /* Collation sequence name */
96847
+ const char *zColl; /* Collation sequence name */
9683396848
9683496849
sqlite3StringToId(pListItem->pExpr);
9683596850
sqlite3ResolveSelfReference(pParse, pTab, NC_IdxExpr, pListItem->pExpr, 0);
9683696851
if( pParse->nErr ) goto exit_create_index;
9683796852
pCExpr = sqlite3ExprSkipCollate(pListItem->pExpr);
@@ -96873,11 +96888,11 @@
9687396888
zExtra += nColl;
9687496889
nExtra -= nColl;
9687596890
}else if( j>=0 ){
9687696891
zColl = pTab->aCol[j].zColl;
9687796892
}
96878
- if( !zColl ) zColl = "BINARY";
96893
+ if( !zColl ) zColl = sqlite3StrBINARY;
9687996894
if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
9688096895
goto exit_create_index;
9688196896
}
9688296897
pIndex->azColl[i] = zColl;
9688396898
requestedSortOrder = pListItem->sortOrder & sortOrderMask;
@@ -96902,11 +96917,11 @@
9690296917
}
9690396918
}
9690496919
assert( i==pIndex->nColumn );
9690596920
}else{
9690696921
pIndex->aiColumn[i] = XN_ROWID;
96907
- pIndex->azColl[i] = "BINARY";
96922
+ pIndex->azColl[i] = sqlite3StrBINARY;
9690896923
}
9690996924
sqlite3DefaultRowEst(pIndex);
9691096925
if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);
9691196926
9691296927
if( pTab==pParse->pNewTable ){
@@ -98026,13 +98041,12 @@
9802698041
pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
9802798042
}
9802898043
if( pKey ){
9802998044
assert( sqlite3KeyInfoIsWriteable(pKey) );
9803098045
for(i=0; i<nCol; i++){
98031
- char *zColl = pIdx->azColl[i];
98032
- assert( zColl!=0 );
98033
- pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 :
98046
+ const char *zColl = pIdx->azColl[i];
98047
+ pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 :
9803498048
sqlite3LocateCollSeq(pParse, zColl);
9803598049
pKey->aSortOrder[i] = pIdx->aSortOrder[i];
9803698050
}
9803798051
if( pParse->nErr ){
9803898052
sqlite3KeyInfoUnref(pKey);
@@ -100238,11 +100252,11 @@
100238100252
continue;
100239100253
}
100240100254
}
100241100255
c2 = Utf8Read(zString);
100242100256
if( c==c2 ) continue;
100243
- if( noCase && c<0x80 && c2<0x80 && sqlite3Tolower(c)==sqlite3Tolower(c2) ){
100257
+ if( noCase && sqlite3Tolower(c)==sqlite3Tolower(c2) ){
100244100258
continue;
100245100259
}
100246100260
if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue;
100247100261
return 0;
100248100262
}
@@ -101557,22 +101571,20 @@
101557101571
** index matches those columns. Also, check that the index uses
101558101572
** the default collation sequences for each column. */
101559101573
int i, j;
101560101574
for(i=0; i<nCol; i++){
101561101575
i16 iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */
101562
- char *zDfltColl; /* Def. collation for column */
101576
+ const char *zDfltColl; /* Def. collation for column */
101563101577
char *zIdxCol; /* Name of indexed column */
101564101578
101565101579
if( iCol<0 ) break; /* No foreign keys against expression indexes */
101566101580
101567101581
/* If the index uses a collation sequence that is different from
101568101582
** the default collation sequence for the column, this index is
101569101583
** unusable. Bail out early in this case. */
101570101584
zDfltColl = pParent->aCol[iCol].zColl;
101571
- if( !zDfltColl ){
101572
- zDfltColl = "BINARY";
101573
- }
101585
+ if( !zDfltColl ) zDfltColl = sqlite3StrBINARY;
101574101586
if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break;
101575101587
101576101588
zIdxCol = pParent->aCol[iCol].zName;
101577101589
for(j=0; j<nCol; j++){
101578101590
if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){
@@ -104430,24 +104442,10 @@
104430104442
SQLITE_API int sqlite3_xferopt_count;
104431104443
#endif /* SQLITE_TEST */
104432104444
104433104445
104434104446
#ifndef SQLITE_OMIT_XFER_OPT
104435
-/*
104436
-** Check to collation names to see if they are compatible.
104437
-*/
104438
-static int xferCompatibleCollation(const char *z1, const char *z2){
104439
- if( z1==0 ){
104440
- return z2==0;
104441
- }
104442
- if( z2==0 ){
104443
- return 0;
104444
- }
104445
- return sqlite3StrICmp(z1, z2)==0;
104446
-}
104447
-
104448
-
104449104447
/*
104450104448
** Check to see if index pSrc is compatible as a source of data
104451104449
** for index pDest in an insert transfer optimization. The rules
104452104450
** for a compatible index:
104453104451
**
@@ -104479,11 +104477,11 @@
104479104477
}
104480104478
}
104481104479
if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){
104482104480
return 0; /* Different sort orders */
104483104481
}
104484
- if( !xferCompatibleCollation(pSrc->azColl[i],pDest->azColl[i]) ){
104482
+ if( sqlite3_stricmp(pSrc->azColl[i],pDest->azColl[i])!=0 ){
104485104483
return 0; /* Different collating sequences */
104486104484
}
104487104485
}
104488104486
if( sqlite3ExprCompare(pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){
104489104487
return 0; /* Different WHERE clauses */
@@ -104640,11 +104638,11 @@
104640104638
}
104641104639
#endif
104642104640
if( pDestCol->affinity!=pSrcCol->affinity ){
104643104641
return 0; /* Affinity must be the same on all columns */
104644104642
}
104645
- if( !xferCompatibleCollation(pDestCol->zColl, pSrcCol->zColl) ){
104643
+ if( sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl)!=0 ){
104646104644
return 0; /* Collating sequence must be the same on all columns */
104647104645
}
104648104646
if( pDestCol->notNull && !pSrcCol->notNull ){
104649104647
return 0; /* tab2 must be NOT NULL if tab1 is */
104650104648
}
@@ -104787,13 +104785,14 @@
104787104785
** BINARY, this optimization is disabled. This is because the user
104788104786
** might change the definition of a collation sequence and then run
104789104787
** a VACUUM command. In that case keys may not be written in strictly
104790104788
** sorted order. */
104791104789
for(i=0; i<pSrcIdx->nColumn; i++){
104792
- char *zColl = pSrcIdx->azColl[i];
104793
- assert( zColl!=0 );
104794
- if( sqlite3_stricmp("BINARY", zColl) ) break;
104790
+ const char *zColl = pSrcIdx->azColl[i];
104791
+ assert( sqlite3_stricmp(sqlite3StrBINARY, zColl)!=0
104792
+ || sqlite3StrBINARY==zColl );
104793
+ if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
104795104794
}
104796104795
if( i==pSrcIdx->nColumn ){
104797104796
idxInsFlags = OPFLAG_USESEEKRESULT;
104798104797
sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1);
104799104798
}
@@ -119290,11 +119289,11 @@
119290119289
** terms in the WHERE clause that are useful to the query planner.
119291119290
*/
119292119291
struct WhereScan {
119293119292
WhereClause *pOrigWC; /* Original, innermost WhereClause */
119294119293
WhereClause *pWC; /* WhereClause currently being scanned */
119295
- char *zCollName; /* Required collating sequence, if not NULL */
119294
+ const char *zCollName; /* Required collating sequence, if not NULL */
119296119295
Expr *pIdxExpr; /* Search for this index expression */
119297119296
char idxaff; /* Must match this affinity, if zCollName!=NULL */
119298119297
unsigned char nEquiv; /* Number of entries in aEquiv[] */
119299119298
unsigned char iEquiv; /* Next unused slot in aEquiv[] */
119300119299
u32 opMask; /* Acceptable operators */
@@ -123276,11 +123275,11 @@
123276123275
if( (idxCols & cMask)==0 ){
123277123276
Expr *pX = pTerm->pExpr;
123278123277
idxCols |= cMask;
123279123278
pIdx->aiColumn[n] = pTerm->u.leftColumn;
123280123279
pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
123281
- pIdx->azColl[n] = pColl ? pColl->zName : "BINARY";
123280
+ pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
123282123281
n++;
123283123282
}
123284123283
}
123285123284
}
123286123285
assert( (u32)n==pLoop->u.btree.nEq );
@@ -123288,24 +123287,24 @@
123288123287
/* Add additional columns needed to make the automatic index into
123289123288
** a covering index */
123290123289
for(i=0; i<mxBitCol; i++){
123291123290
if( extraCols & MASKBIT(i) ){
123292123291
pIdx->aiColumn[n] = i;
123293
- pIdx->azColl[n] = "BINARY";
123292
+ pIdx->azColl[n] = sqlite3StrBINARY;
123294123293
n++;
123295123294
}
123296123295
}
123297123296
if( pSrc->colUsed & MASKBIT(BMS-1) ){
123298123297
for(i=BMS-1; i<pTable->nCol; i++){
123299123298
pIdx->aiColumn[n] = i;
123300
- pIdx->azColl[n] = "BINARY";
123299
+ pIdx->azColl[n] = sqlite3StrBINARY;
123301123300
n++;
123302123301
}
123303123302
}
123304123303
assert( n==nKeyCol );
123305123304
pIdx->aiColumn[n] = XN_ROWID;
123306
- pIdx->azColl[n] = "BINARY";
123305
+ pIdx->azColl[n] = sqlite3StrBINARY;
123307123306
123308123307
/* Create the automatic index */
123309123308
assert( pLevel->iIdxCur>=0 );
123310123309
pLevel->iIdxCur = pParse->nTab++;
123311123310
sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1);
@@ -134856,22 +134855,22 @@
134856134855
** conversions. The only error that can occur here is a malloc() failure.
134857134856
**
134858134857
** EVIDENCE-OF: R-52786-44878 SQLite defines three built-in collating
134859134858
** functions:
134860134859
*/
134861
- createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0);
134862
- createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0);
134863
- createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0);
134860
+ createCollation(db, sqlite3StrBINARY, SQLITE_UTF8, 0, binCollFunc, 0);
134861
+ createCollation(db, sqlite3StrBINARY, SQLITE_UTF16BE, 0, binCollFunc, 0);
134862
+ createCollation(db, sqlite3StrBINARY, SQLITE_UTF16LE, 0, binCollFunc, 0);
134864134863
createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0);
134865134864
createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0);
134866134865
if( db->mallocFailed ){
134867134866
goto opendb_out;
134868134867
}
134869134868
/* EVIDENCE-OF: R-08308-17224 The default collating function for all
134870134869
** strings is BINARY.
134871134870
*/
134872
- db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0);
134871
+ db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, sqlite3StrBINARY, 0);
134873134872
assert( db->pDfltColl!=0 );
134874134873
134875134874
/* Parse the filename/URI argument. */
134876134875
db->openFlags = flags;
134877134876
rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
@@ -135367,11 +135366,11 @@
135367135366
}else{
135368135367
zDataType = "INTEGER";
135369135368
primarykey = 1;
135370135369
}
135371135370
if( !zCollSeq ){
135372
- zCollSeq = "BINARY";
135371
+ zCollSeq = sqlite3StrBINARY;
135373135372
}
135374135373
135375135374
error_out:
135376135375
sqlite3BtreeLeaveAll(db);
135377135376
@@ -135975,11 +135974,10 @@
135975135974
*/
135976135975
SQLITE_API void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){
135977135976
sqlite3_free(pSnapshot);
135978135977
}
135979135978
#endif /* SQLITE_ENABLE_SNAPSHOT */
135980
-
135981135979
135982135980
/************** End of main.c ************************************************/
135983135981
/************** Begin file notify.c ******************************************/
135984135982
/*
135985135983
** 2009 March 3
@@ -166096,11 +166094,11 @@
166096166094
sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE);
166097166095
}
166098166096
#endif /* SQLITE_DEBUG */
166099166097
166100166098
/****************************************************************************
166101
-** SQL function implementations
166099
+** Scalar SQL function implementations
166102166100
****************************************************************************/
166103166101
166104166102
/*
166105166103
** Implementation of the json_array(VALUE,...) function. Return a JSON
166106166104
** array that contains all values given in arguments. Or if any argument
@@ -166428,10 +166426,106 @@
166428166426
rc = 1;
166429166427
}
166430166428
jsonParseReset(&x);
166431166429
sqlite3_result_int(ctx, rc);
166432166430
}
166431
+
166432
+
166433
+/****************************************************************************
166434
+** Aggregate SQL function implementations
166435
+****************************************************************************/
166436
+/*
166437
+** json_group_array(VALUE)
166438
+**
166439
+** Return a JSON array composed of all values in the aggregate.
166440
+*/
166441
+static void jsonArrayStep(
166442
+ sqlite3_context *ctx,
166443
+ int argc,
166444
+ sqlite3_value **argv
166445
+){
166446
+ JsonString *pStr;
166447
+ pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
166448
+ if( pStr ){
166449
+ if( pStr->zBuf==0 ){
166450
+ jsonInit(pStr, ctx);
166451
+ jsonAppendChar(pStr, '[');
166452
+ }else{
166453
+ jsonAppendChar(pStr, ',');
166454
+ pStr->pCtx = ctx;
166455
+ }
166456
+ jsonAppendValue(pStr, argv[0]);
166457
+ }
166458
+}
166459
+static void jsonArrayFinal(sqlite3_context *ctx){
166460
+ JsonString *pStr;
166461
+ pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
166462
+ if( pStr ){
166463
+ pStr->pCtx = ctx;
166464
+ jsonAppendChar(pStr, ']');
166465
+ if( pStr->bErr ){
166466
+ sqlite3_result_error_nomem(ctx);
166467
+ assert( pStr->bStatic );
166468
+ }else{
166469
+ sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
166470
+ pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
166471
+ pStr->bStatic = 1;
166472
+ }
166473
+ }else{
166474
+ sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
166475
+ }
166476
+ sqlite3_result_subtype(ctx, JSON_SUBTYPE);
166477
+}
166478
+
166479
+/*
166480
+** json_group_obj(NAME,VALUE)
166481
+**
166482
+** Return a JSON object composed of all names and values in the aggregate.
166483
+*/
166484
+static void jsonObjectStep(
166485
+ sqlite3_context *ctx,
166486
+ int argc,
166487
+ sqlite3_value **argv
166488
+){
166489
+ JsonString *pStr;
166490
+ const char *z;
166491
+ u32 n;
166492
+ pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
166493
+ if( pStr ){
166494
+ if( pStr->zBuf==0 ){
166495
+ jsonInit(pStr, ctx);
166496
+ jsonAppendChar(pStr, '{');
166497
+ }else{
166498
+ jsonAppendChar(pStr, ',');
166499
+ pStr->pCtx = ctx;
166500
+ }
166501
+ z = (const char*)sqlite3_value_text(argv[0]);
166502
+ n = (u32)sqlite3_value_bytes(argv[0]);
166503
+ jsonAppendString(pStr, z, n);
166504
+ jsonAppendChar(pStr, ':');
166505
+ jsonAppendValue(pStr, argv[1]);
166506
+ }
166507
+}
166508
+static void jsonObjectFinal(sqlite3_context *ctx){
166509
+ JsonString *pStr;
166510
+ pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
166511
+ if( pStr ){
166512
+ jsonAppendChar(pStr, '}');
166513
+ if( pStr->bErr ){
166514
+ sqlite3_result_error_nomem(ctx);
166515
+ assert( pStr->bStatic );
166516
+ }else{
166517
+ sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
166518
+ pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
166519
+ pStr->bStatic = 1;
166520
+ }
166521
+ }else{
166522
+ sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
166523
+ }
166524
+ sqlite3_result_subtype(ctx, JSON_SUBTYPE);
166525
+}
166526
+
166433166527
166434166528
#ifndef SQLITE_OMIT_VIRTUALTABLE
166435166529
/****************************************************************************
166436166530
** The json_each virtual table
166437166531
****************************************************************************/
@@ -166927,10 +167021,19 @@
166927167021
/* DEBUG and TESTING functions */
166928167022
{ "json_parse", 1, 0, jsonParseFunc },
166929167023
{ "json_test1", 1, 0, jsonTest1Func },
166930167024
#endif
166931167025
};
167026
+ static const struct {
167027
+ const char *zName;
167028
+ int nArg;
167029
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**);
167030
+ void (*xFinal)(sqlite3_context*);
167031
+ } aAgg[] = {
167032
+ { "json_group_array", 1, jsonArrayStep, jsonArrayFinal },
167033
+ { "json_group_object", 2, jsonObjectStep, jsonObjectFinal },
167034
+ };
166932167035
#ifndef SQLITE_OMIT_VIRTUALTABLE
166933167036
static const struct {
166934167037
const char *zName;
166935167038
sqlite3_module *pModule;
166936167039
} aMod[] = {
@@ -166942,10 +167045,15 @@
166942167045
rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
166943167046
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
166944167047
(void*)&aFunc[i].flag,
166945167048
aFunc[i].xFunc, 0, 0);
166946167049
}
167050
+ for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
167051
+ rc = sqlite3_create_function(db, aAgg[i].zName, aAgg[i].nArg,
167052
+ SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
167053
+ 0, aAgg[i].xStep, aAgg[i].xFinal);
167054
+ }
166947167055
#ifndef SQLITE_OMIT_VIRTUALTABLE
166948167056
for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){
166949167057
rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0);
166950167058
}
166951167059
#endif
@@ -169981,11 +170089,11 @@
169981170089
{ "bm25", 0, fts5Bm25Function, 0 },
169982170090
};
169983170091
int rc = SQLITE_OK; /* Return code */
169984170092
int i; /* To iterate through builtin functions */
169985170093
169986
- for(i=0; rc==SQLITE_OK && i<sizeof(aBuiltin)/sizeof(aBuiltin[0]); i++){
170094
+ for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){
169987170095
rc = pApi->xCreateFunction(pApi,
169988170096
aBuiltin[i].zFunc,
169989170097
aBuiltin[i].pUserData,
169990170098
aBuiltin[i].xFunc,
169991170099
aBuiltin[i].xDestroy
@@ -171605,11 +171713,11 @@
171605171713
171606171714
fts5BufferZero(&pPhrase->poslist);
171607171715
171608171716
/* If the aStatic[] array is not large enough, allocate a large array
171609171717
** using sqlite3_malloc(). This approach could be improved upon. */
171610
- if( pPhrase->nTerm>(sizeof(aStatic) / sizeof(aStatic[0])) ){
171718
+ if( pPhrase->nTerm>(int)ArraySize(aStatic) ){
171611171719
int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
171612171720
aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte);
171613171721
if( !aIter ) return SQLITE_NOMEM;
171614171722
}
171615171723
memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm);
@@ -171741,11 +171849,11 @@
171741171849
171742171850
assert( pNear->nPhrase>1 );
171743171851
171744171852
/* If the aStatic[] array is not large enough, allocate a large array
171745171853
** using sqlite3_malloc(). This approach could be improved upon. */
171746
- if( pNear->nPhrase>(sizeof(aStatic) / sizeof(aStatic[0])) ){
171854
+ if( pNear->nPhrase>(int)ArraySize(aStatic) ){
171747171855
int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
171748171856
a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte);
171749171857
}else{
171750171858
memset(aStatic, 0, sizeof(aStatic));
171751171859
}
@@ -173388,11 +173496,11 @@
173388173496
};
173389173497
int i;
173390173498
int rc = SQLITE_OK;
173391173499
void *pCtx = (void*)pGlobal;
173392173500
173393
- for(i=0; rc==SQLITE_OK && i<(sizeof(aFunc) / sizeof(aFunc[0])); i++){
173501
+ for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aFunc); i++){
173394173502
struct Fts5ExprFunc *p = &aFunc[i];
173395173503
rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
173396173504
}
173397173505
173398173506
/* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */
@@ -180242,11 +180350,11 @@
180242180350
180243180351
/* Set idxFlags flags for all WHERE clause terms that will be used. */
180244180352
for(i=0; i<pInfo->nConstraint; i++){
180245180353
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
180246180354
int j;
180247
- for(j=0; j<sizeof(aConstraint)/sizeof(aConstraint[0]); j++){
180355
+ for(j=0; j<(int)ArraySize(aConstraint); j++){
180248180356
struct Constraint *pC = &aConstraint[j];
180249180357
if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){
180250180358
if( p->usable ){
180251180359
pC->iConsIndex = i;
180252180360
idxFlags |= pC->fts5op;
@@ -180289,11 +180397,11 @@
180289180397
pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0;
180290180398
}
180291180399
180292180400
/* Assign argvIndex values to each constraint in use. */
180293180401
iNext = 1;
180294
- for(i=0; i<sizeof(aConstraint)/sizeof(aConstraint[0]); i++){
180402
+ for(i=0; i<(int)ArraySize(aConstraint); i++){
180295180403
struct Constraint *pC = &aConstraint[i];
180296180404
if( pC->iConsIndex>=0 ){
180297180405
pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++;
180298180406
pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit;
180299180407
}
@@ -182139,11 +182247,11 @@
182139182247
sqlite3_context *pCtx, /* Function call context */
182140182248
int nArg, /* Number of args */
182141182249
sqlite3_value **apVal /* Function arguments */
182142182250
){
182143182251
assert( nArg==0 );
182144
- sqlite3_result_text(pCtx, "fts5: 2015-12-18 16:29:47 8bf5e056eb8beb6e0ed5874fb24d7fe9f0b66d2b", -1, SQLITE_TRANSIENT);
182252
+ sqlite3_result_text(pCtx, "fts5: 2016-01-06 11:01:07 fd0a50f0797d154fefff724624f00548b5320566", -1, SQLITE_TRANSIENT);
182145182253
}
182146182254
182147182255
static int fts5Init(sqlite3 *db){
182148182256
static const sqlite3_module fts5Mod = {
182149182257
/* iVersion */ 2,
@@ -182584,11 +182692,11 @@
182584182692
int rc = SQLITE_OK;
182585182693
if( p ){
182586182694
int i;
182587182695
182588182696
/* Finalize all SQL statements */
182589
- for(i=0; i<ArraySize(p->aStmt); i++){
182697
+ for(i=0; i<(int)ArraySize(p->aStmt); i++){
182590182698
sqlite3_finalize(p->aStmt[i]);
182591182699
}
182592182700
182593182701
sqlite3_free(p);
182594182702
}
@@ -184570,11 +184678,11 @@
184570184678
};
184571184679
184572184680
int rc = SQLITE_OK; /* Return code */
184573184681
int i; /* To iterate through builtin functions */
184574184682
184575
- for(i=0; rc==SQLITE_OK && i<sizeof(aBuiltin)/sizeof(aBuiltin[0]); i++){
184683
+ for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){
184576184684
rc = pApi->xCreateTokenizer(pApi,
184577184685
aBuiltin[i].zName,
184578184686
(void*)pApi,
184579184687
&aBuiltin[i].x,
184580184688
0
184581184689
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -325,11 +325,11 @@
325 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
326 ** [sqlite_version()] and [sqlite_source_id()].
327 */
328 #define SQLITE_VERSION "3.10.0"
329 #define SQLITE_VERSION_NUMBER 3010000
330 #define SQLITE_SOURCE_ID "2015-12-23 10:54:48 b910a3d53769689d9212a06f974ccce54844bbe4"
331
332 /*
333 ** CAPI3REF: Run-Time Library Version Numbers
334 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
335 **
@@ -9901,15 +9901,10 @@
9901 ** For best performance, an attempt is made to guess at the byte-order
9902 ** using C-preprocessor macros. If that is unsuccessful, or if
9903 ** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
9904 ** at run-time.
9905 */
9906 #ifdef SQLITE_AMALGAMATION
9907 SQLITE_PRIVATE const int sqlite3one = 1;
9908 #else
9909 SQLITE_PRIVATE const int sqlite3one;
9910 #endif
9911 #if (defined(i386) || defined(__i386__) || defined(_M_IX86) || \
9912 defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
9913 defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
9914 defined(__arm__)) && !defined(SQLITE_RUNTIME_BYTEORDER)
9915 # define SQLITE_BYTEORDER 1234
@@ -9923,10 +9918,15 @@
9923 # define SQLITE_BIGENDIAN 1
9924 # define SQLITE_LITTLEENDIAN 0
9925 # define SQLITE_UTF16NATIVE SQLITE_UTF16BE
9926 #endif
9927 #if !defined(SQLITE_BYTEORDER)
 
 
 
 
 
9928 # define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */
9929 # define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
9930 # define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
9931 # define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
9932 #endif
@@ -12317,11 +12317,11 @@
12317 char *zDflt; /* Original text of the default value */
12318 char *zType; /* Data type for this column */
12319 char *zColl; /* Collating sequence. If NULL, use the default */
12320 u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
12321 char affinity; /* One of the SQLITE_AFF_... values */
12322 u8 szEst; /* Estimated size of this column. INT==1 */
12323 u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */
12324 };
12325
12326 /* Allowed values for Column.colFlags:
12327 */
@@ -12727,11 +12727,11 @@
12727 Table *pTable; /* The SQL table being indexed */
12728 char *zColAff; /* String defining the affinity of each column */
12729 Index *pNext; /* The next index associated with the same table */
12730 Schema *pSchema; /* Schema containing this index */
12731 u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
12732 char **azColl; /* Array of collation sequence names for index */
12733 Expr *pPartIdxWhere; /* WHERE clause for partial indices */
12734 ExprList *aColExpr; /* Column expressions */
12735 int tnum; /* DB Page containing root of this index */
12736 LogEst szIdxRow; /* Estimated average row size in bytes */
12737 u16 nKeyCol; /* Number of columns forming the key */
@@ -13527,10 +13527,11 @@
13527 int nTab; /* Number of previously allocated VDBE cursors */
13528 int nMem; /* Number of memory cells used so far */
13529 int nSet; /* Number of sets used so far */
13530 int nOnce; /* Number of OP_Once instructions so far */
13531 int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
 
13532 int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */
13533 int ckBase; /* Base register of data during check constraints */
13534 int iSelfTab; /* Table of an index whose exprs are being coded */
13535 int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
13536 int iCacheCnt; /* Counter used to generate aColCache[].lru values */
@@ -13758,13 +13759,13 @@
13758 */
13759 struct StrAccum {
13760 sqlite3 *db; /* Optional database for lookaside. Can be NULL */
13761 char *zBase; /* A base allocation. Not from malloc. */
13762 char *zText; /* The string collected so far */
13763 int nChar; /* Length of the string so far */
13764 int nAlloc; /* Amount of space allocated in zText */
13765 int mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */
13766 u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
13767 u8 bMalloced; /* zText points to allocated space */
13768 };
13769 #define STRACCUM_NOMEM 1
13770 #define STRACCUM_TOOBIG 2
@@ -14143,11 +14144,15 @@
14143 SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
14144 SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
14145 SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*);
14146 SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index*, i16);
14147 SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
14148 SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*);
 
 
 
 
14149 SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*);
14150 SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
14151 SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
14152 SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
14153 SQLITE_PRIVATE void sqlite3AddColumnType(Parse*,Token*);
@@ -14494,10 +14499,11 @@
14494 SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
14495 SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
14496 SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
14497 #ifndef SQLITE_AMALGAMATION
14498 SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[];
 
14499 SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
14500 SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[];
14501 SQLITE_PRIVATE const Token sqlite3IntTokens[];
14502 SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config;
14503 SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
@@ -15099,10 +15105,15 @@
15099 ** from the comments following the "case OP_xxxx:" statements in
15100 ** the vdbe.c file.
15101 */
15102 SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
15103
 
 
 
 
 
15104 /************** End of global.c **********************************************/
15105 /************** Begin file ctime.c *******************************************/
15106 /*
15107 ** 2010 February 23
15108 **
@@ -20655,10 +20666,12 @@
20655 int trace; /* True to trace changes */
20656 #endif
20657 };
20658 #if SQLITE_MUTEX_NREF
20659 #define SQLITE3_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,0,0,(pthread_t)0,0}
 
 
20660 #else
20661 #define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
20662 #endif
20663
20664 /*
@@ -24490,17 +24503,17 @@
24490 */
24491 /* #include "sqliteInt.h" */
24492 /* #include <assert.h> */
24493 /* #include "vdbeInt.h" */
24494
24495 #ifndef SQLITE_AMALGAMATION
24496 /*
24497 ** The following constant value is used by the SQLITE_BIGENDIAN and
24498 ** SQLITE_LITTLEENDIAN macros.
24499 */
24500 SQLITE_PRIVATE const int sqlite3one = 1;
24501 #endif /* SQLITE_AMALGAMATION */
24502
24503 /*
24504 ** This lookup table is used to help decode the first byte of
24505 ** a multi-byte UTF8 character.
24506 */
@@ -54549,11 +54562,10 @@
54549 struct CellInfo {
54550 i64 nKey; /* The key for INTKEY tables, or nPayload otherwise */
54551 u8 *pPayload; /* Pointer to the start of payload */
54552 u32 nPayload; /* Bytes of payload */
54553 u16 nLocal; /* Amount of payload held locally, not on overflow */
54554 u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */
54555 u16 nSize; /* Size of the cell content on the main b-tree page */
54556 };
54557
54558 /*
54559 ** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than
@@ -56130,12 +56142,11 @@
56130 if( surplus <= maxLocal ){
56131 pInfo->nLocal = (u16)surplus;
56132 }else{
56133 pInfo->nLocal = (u16)minLocal;
56134 }
56135 pInfo->iOverflow = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell);
56136 pInfo->nSize = pInfo->iOverflow + 4;
56137 }
56138
56139 /*
56140 ** The following routines are implementations of the MemPage.xParseCell()
56141 ** method.
@@ -56163,11 +56174,10 @@
56163 UNUSED_PARAMETER(pPage);
56164 #endif
56165 pInfo->nSize = 4 + getVarint(&pCell[4], (u64*)&pInfo->nKey);
56166 pInfo->nPayload = 0;
56167 pInfo->nLocal = 0;
56168 pInfo->iOverflow = 0;
56169 pInfo->pPayload = 0;
56170 return;
56171 }
56172 static void btreeParseCellPtr(
56173 MemPage *pPage, /* Page containing the cell */
@@ -56233,11 +56243,10 @@
56233 ** on the local page. No overflow is required.
56234 */
56235 pInfo->nSize = nPayload + (u16)(pIter - pCell);
56236 if( pInfo->nSize<4 ) pInfo->nSize = 4;
56237 pInfo->nLocal = (u16)nPayload;
56238 pInfo->iOverflow = 0;
56239 }else{
56240 btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo);
56241 }
56242 }
56243 static void btreeParseCellPtrIndex(
@@ -56272,11 +56281,10 @@
56272 ** on the local page. No overflow is required.
56273 */
56274 pInfo->nSize = nPayload + (u16)(pIter - pCell);
56275 if( pInfo->nSize<4 ) pInfo->nSize = 4;
56276 pInfo->nLocal = (u16)nPayload;
56277 pInfo->iOverflow = 0;
56278 }else{
56279 btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo);
56280 }
56281 }
56282 static void btreeParseCell(
@@ -56388,12 +56396,12 @@
56388 static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
56389 CellInfo info;
56390 if( *pRC ) return;
56391 assert( pCell!=0 );
56392 pPage->xParseCell(pPage, pCell, &info);
56393 if( info.iOverflow ){
56394 Pgno ovfl = get4byte(&pCell[info.iOverflow]);
56395 ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC);
56396 }
56397 }
56398 #endif
56399
@@ -58427,15 +58435,15 @@
58427 for(i=0; i<nCell; i++){
58428 u8 *pCell = findCell(pPage, i);
58429 if( eType==PTRMAP_OVERFLOW1 ){
58430 CellInfo info;
58431 pPage->xParseCell(pPage, pCell, &info);
58432 if( info.iOverflow
58433 && pCell+info.iOverflow+3<=pPage->aData+pPage->maskPage
58434 && iFrom==get4byte(&pCell[info.iOverflow])
58435 ){
58436 put4byte(&pCell[info.iOverflow], iTo);
58437 break;
58438 }
58439 }else{
58440 if( get4byte(pCell)==iFrom ){
58441 put4byte(pCell, iTo);
@@ -61073,17 +61081,17 @@
61073 u32 ovflPageSize;
61074
61075 assert( sqlite3_mutex_held(pPage->pBt->mutex) );
61076 pPage->xParseCell(pPage, pCell, &info);
61077 *pnSize = info.nSize;
61078 if( info.iOverflow==0 ){
61079 return SQLITE_OK; /* No overflow pages. Return without doing anything */
61080 }
61081 if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){
61082 return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */
61083 }
61084 ovflPgno = get4byte(&pCell[info.iOverflow]);
61085 assert( pBt->usableSize > 4 );
61086 ovflPageSize = pBt->usableSize - 4;
61087 nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
61088 assert( nOvfl>0 ||
61089 (CORRUPT_DB && (info.nPayload + ovflPageSize)<ovflPageSize)
@@ -61228,11 +61236,10 @@
61228 pPage->xParseCell(pPage, pCell, &info);
61229 assert( nHeader=(int)(info.pPayload - pCell) );
61230 assert( info.nKey==nKey );
61231 assert( *pnSize == info.nSize );
61232 assert( spaceLeft == info.nLocal );
61233 assert( pPrior == &pCell[info.iOverflow] );
61234 }
61235 #endif
61236
61237 /* Write the payload into the local Cell and any extra into overflow pages */
61238 while( nPayload>0 ){
@@ -61938,12 +61945,12 @@
61938 CellInfo info;
61939 u8 *z;
61940
61941 z = findCell(pPage, j);
61942 pPage->xParseCell(pPage, z, &info);
61943 if( info.iOverflow ){
61944 Pgno ovfl = get4byte(&z[info.iOverflow]);
61945 ptrmapGet(pBt, ovfl, &e, &n);
61946 assert( n==pPage->pgno && e==PTRMAP_OVERFLOW1 );
61947 }
61948 if( !pPage->leaf ){
61949 Pgno child = get4byte(z);
@@ -63305,11 +63312,11 @@
63305 rc = balance(pCur);
63306 }
63307
63308 if( rc==SQLITE_OK ){
63309 if( bSkipnext ){
63310 assert( bPreserve && pCur->iPage==iCellDepth );
63311 assert( pPage==pCur->apPage[pCur->iPage] );
63312 assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell );
63313 pCur->eState = CURSOR_SKIPNEXT;
63314 if( iCellIdx>=pPage->nCell ){
63315 pCur->skipNext = -1;
@@ -64245,13 +64252,13 @@
64245
64246 /* Check the content overflow list */
64247 if( info.nPayload>info.nLocal ){
64248 int nPage; /* Number of pages on the overflow chain */
64249 Pgno pgnoOvfl; /* First page of the overflow chain */
64250 assert( pc + info.iOverflow <= usableSize );
64251 nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
64252 pgnoOvfl = get4byte(&pCell[info.iOverflow]);
64253 #ifndef SQLITE_OMIT_AUTOVACUUM
64254 if( pBt->autoVacuum ){
64255 checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage);
64256 }
64257 #endif
@@ -67316,10 +67323,11 @@
67316 p->magic = VDBE_MAGIC_INIT;
67317 p->pParse = pParse;
67318 assert( pParse->aLabel==0 );
67319 assert( pParse->nLabel==0 );
67320 assert( pParse->nOpAlloc==0 );
 
67321 return p;
67322 }
67323
67324 /*
67325 ** Change the error string stored in Vdbe.zErrMsg
@@ -67405,11 +67413,12 @@
67405
67406 assert( nOp<=(1024/sizeof(Op)) );
67407 assert( nNew>=(p->nOpAlloc+nOp) );
67408 pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
67409 if( pNew ){
67410 p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op);
 
67411 v->aOp = pNew;
67412 }
67413 return (pNew ? SQLITE_OK : SQLITE_NOMEM);
67414 }
67415
@@ -69127,24 +69136,31 @@
69127 **
69128 ** See also: allocateCursor().
69129 */
69130 nMem += nCursor;
69131
69132 /* Allocate space for memory registers, SQL variables, VDBE cursors and
69133 ** an array to marshal SQL function arguments in.
 
 
 
69134 */
69135 zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */
69136 assert( pParse->nOpAlloc*sizeof(Op) <= 0x7fffff00 );
69137 nFree = (pParse->nOpAlloc - p->nOp)*sizeof(p->aOp[0]); /* Available space */
 
 
 
 
 
 
69138
69139 resolveP2Values(p, &nArg);
69140 p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
69141 if( pParse->explain && nMem<10 ){
69142 nMem = 10;
69143 }
69144 memset(zCsr, 0, nFree);
69145 assert( EIGHT_BYTE_ALIGNMENT(&zCsr[nFree]) );
69146 p->expired = 0;
69147
69148 /* Memory for registers, parameters, cursor, etc, is allocated in two
69149 ** passes. On the first pass, we try to reuse unused space at the
69150 ** end of the opcode array. If we are unable to satisfy all memory
@@ -71029,11 +71045,11 @@
71029 }
71030 if( (f2 & MEM_Str)==0 ){
71031 return -1;
71032 }
71033
71034 assert( pMem1->enc==pMem2->enc );
71035 assert( pMem1->enc==SQLITE_UTF8 ||
71036 pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
71037
71038 /* The collation sequence must be defined at this point, even if
71039 ** the user deletes the collation sequence after the vdbe program is
@@ -75665,42 +75681,41 @@
75665 }
75666 }else{
75667 /* Neither operand is NULL. Do a comparison. */
75668 affinity = pOp->p5 & SQLITE_AFF_MASK;
75669 if( affinity>=SQLITE_AFF_NUMERIC ){
75670 if( (pIn1->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
75671 applyNumericAffinity(pIn1,0);
75672 }
75673 if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
75674 applyNumericAffinity(pIn3,0);
75675 }
75676 }else if( affinity==SQLITE_AFF_TEXT ){
75677 if( (pIn1->flags & MEM_Str)==0 && (pIn1->flags & (MEM_Int|MEM_Real))!=0 ){
75678 testcase( pIn1->flags & MEM_Int );
75679 testcase( pIn1->flags & MEM_Real );
75680 sqlite3VdbeMemStringify(pIn1, encoding, 1);
75681 testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
75682 flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
75683 }
75684 if( (pIn3->flags & MEM_Str)==0 && (pIn3->flags & (MEM_Int|MEM_Real))!=0 ){
75685 testcase( pIn3->flags & MEM_Int );
75686 testcase( pIn3->flags & MEM_Real );
75687 sqlite3VdbeMemStringify(pIn3, encoding, 1);
75688 testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
75689 flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
75690 }
75691 }
75692 assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
75693 if( pIn1->flags & MEM_Zero ){
75694 sqlite3VdbeMemExpandBlob(pIn1);
75695 flags1 &= ~MEM_Zero;
75696 }
75697 if( pIn3->flags & MEM_Zero ){
75698 sqlite3VdbeMemExpandBlob(pIn3);
75699 flags3 &= ~MEM_Zero;
75700 }
75701 if( db->mallocFailed ) goto no_mem;
75702 res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
75703 }
75704 switch( pOp->opcode ){
75705 case OP_Eq: res = res==0; break;
75706 case OP_Ne: res = res!=0; break;
@@ -76194,11 +76209,11 @@
76194 ){
76195 rc = SQLITE_CORRUPT_BKPT;
76196 goto op_column_error;
76197 }
76198 }else{
76199 VVA_ONLY( t = 0; ) /* Only needed by assert() statements */
76200 }
76201
76202 /* If after trying to extract new entries from the header, nHdrParsed is
76203 ** still not up to p2, that means that the record has fewer than p2
76204 ** columns. So the result will be either the default value or a NULL.
@@ -77072,11 +77087,11 @@
77072
77073 open_cursor_set_hints:
77074 assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
77075 assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
77076 testcase( pOp->p5 & OPFLAG_BULKCSR );
77077 #ifdef SQLITE_ENABLE_CURSOR_HINT
77078 testcase( pOp->p2 & OPFLAG_SEEKEQ );
77079 #endif
77080 sqlite3BtreeCursorHintFlags(pCur->uc.pCursor,
77081 (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
77082 break;
@@ -86739,11 +86754,11 @@
86739 }
86740 if( isReduced ){
86741 assert( ExprHasProperty(p, EP_Reduced)==0 );
86742 memcpy(zAlloc, p, nNewSize);
86743 }else{
86744 int nSize = exprStructSize(p);
86745 memcpy(zAlloc, p, nSize);
86746 if( nSize<EXPR_FULLSIZE ){
86747 memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
86748 }
86749 }
@@ -94128,11 +94143,11 @@
94128 sqlite3DeleteIndexSamples(db, p);
94129 #endif
94130 sqlite3ExprDelete(db, p->pPartIdxWhere);
94131 sqlite3ExprListDelete(db, p->aColExpr);
94132 sqlite3DbFree(db, p->zColAff);
94133 if( p->isResized ) sqlite3DbFree(db, p->azColl);
94134 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
94135 sqlite3_free(p->aiRowEst);
94136 #endif
94137 sqlite3DbFree(db, p);
94138 }
@@ -94731,19 +94746,19 @@
94731 }
94732
94733 /* Set properties of a table column based on the (magical)
94734 ** name of the column.
94735 */
94736 SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
94737 #if SQLITE_ENABLE_HIDDEN_COLUMNS
 
94738 if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){
94739 pCol->colFlags |= COLFLAG_HIDDEN;
94740 }else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){
94741 pTab->tabFlags |= TF_OOOHidden;
94742 }
 
94743 #endif
94744 }
94745
94746
94747 /*
94748 ** Add a new column to the table currently being constructed.
94749 **
@@ -95319,11 +95334,11 @@
95319 assert( pIdx->isResized==0 );
95320 nByte = (sizeof(char*) + sizeof(i16) + 1)*N;
95321 zExtra = sqlite3DbMallocZero(db, nByte);
95322 if( zExtra==0 ) return SQLITE_NOMEM;
95323 memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
95324 pIdx->azColl = (char**)zExtra;
95325 zExtra += sizeof(char*)*N;
95326 memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn);
95327 pIdx->aiColumn = (i16*)zExtra;
95328 zExtra += sizeof(i16)*N;
95329 memcpy(zExtra, pIdx->aSortOrder, pIdx->nColumn);
@@ -95458,11 +95473,11 @@
95458
95459 /* Make sure every column of the PRIMARY KEY is NOT NULL. (Except,
95460 ** do not enforce this for imposter tables.) */
95461 if( !db->init.imposterTable ){
95462 for(i=0; i<nPk; i++){
95463 pTab->aCol[pPk->aiColumn[i]].notNull = 1;
95464 }
95465 pPk->uniqNotNull = 1;
95466 }
95467
95468 /* The root page of the PRIMARY KEY is the table root page */
@@ -95500,11 +95515,11 @@
95500 if( resizeIndexObject(db, pPk, pTab->nCol) ) return;
95501 for(i=0, j=nPk; i<pTab->nCol; i++){
95502 if( !hasColumn(pPk->aiColumn, j, i) ){
95503 assert( j<pPk->nColumn );
95504 pPk->aiColumn[j] = i;
95505 pPk->azColl[j] = "BINARY";
95506 j++;
95507 }
95508 }
95509 assert( pPk->nColumn==j );
95510 assert( pTab->nCol==j );
@@ -96550,11 +96565,11 @@
96550 sizeof(i16)*nCol + /* Index.aiColumn */
96551 sizeof(u8)*nCol); /* Index.aSortOrder */
96552 p = sqlite3DbMallocZero(db, nByte + nExtra);
96553 if( p ){
96554 char *pExtra = ((char*)p)+ROUND8(sizeof(Index));
96555 p->azColl = (char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol);
96556 p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1);
96557 p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol;
96558 p->aSortOrder = (u8*)pExtra;
96559 p->nColumn = nCol;
96560 p->nKeyCol = nCol - 1;
@@ -96827,11 +96842,11 @@
96827 ** index key.
96828 */
96829 for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
96830 Expr *pCExpr; /* The i-th index expression */
96831 int requestedSortOrder; /* ASC or DESC on the i-th expression */
96832 char *zColl; /* Collation sequence name */
96833
96834 sqlite3StringToId(pListItem->pExpr);
96835 sqlite3ResolveSelfReference(pParse, pTab, NC_IdxExpr, pListItem->pExpr, 0);
96836 if( pParse->nErr ) goto exit_create_index;
96837 pCExpr = sqlite3ExprSkipCollate(pListItem->pExpr);
@@ -96873,11 +96888,11 @@
96873 zExtra += nColl;
96874 nExtra -= nColl;
96875 }else if( j>=0 ){
96876 zColl = pTab->aCol[j].zColl;
96877 }
96878 if( !zColl ) zColl = "BINARY";
96879 if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
96880 goto exit_create_index;
96881 }
96882 pIndex->azColl[i] = zColl;
96883 requestedSortOrder = pListItem->sortOrder & sortOrderMask;
@@ -96902,11 +96917,11 @@
96902 }
96903 }
96904 assert( i==pIndex->nColumn );
96905 }else{
96906 pIndex->aiColumn[i] = XN_ROWID;
96907 pIndex->azColl[i] = "BINARY";
96908 }
96909 sqlite3DefaultRowEst(pIndex);
96910 if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);
96911
96912 if( pTab==pParse->pNewTable ){
@@ -98026,13 +98041,12 @@
98026 pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
98027 }
98028 if( pKey ){
98029 assert( sqlite3KeyInfoIsWriteable(pKey) );
98030 for(i=0; i<nCol; i++){
98031 char *zColl = pIdx->azColl[i];
98032 assert( zColl!=0 );
98033 pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 :
98034 sqlite3LocateCollSeq(pParse, zColl);
98035 pKey->aSortOrder[i] = pIdx->aSortOrder[i];
98036 }
98037 if( pParse->nErr ){
98038 sqlite3KeyInfoUnref(pKey);
@@ -100238,11 +100252,11 @@
100238 continue;
100239 }
100240 }
100241 c2 = Utf8Read(zString);
100242 if( c==c2 ) continue;
100243 if( noCase && c<0x80 && c2<0x80 && sqlite3Tolower(c)==sqlite3Tolower(c2) ){
100244 continue;
100245 }
100246 if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue;
100247 return 0;
100248 }
@@ -101557,22 +101571,20 @@
101557 ** index matches those columns. Also, check that the index uses
101558 ** the default collation sequences for each column. */
101559 int i, j;
101560 for(i=0; i<nCol; i++){
101561 i16 iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */
101562 char *zDfltColl; /* Def. collation for column */
101563 char *zIdxCol; /* Name of indexed column */
101564
101565 if( iCol<0 ) break; /* No foreign keys against expression indexes */
101566
101567 /* If the index uses a collation sequence that is different from
101568 ** the default collation sequence for the column, this index is
101569 ** unusable. Bail out early in this case. */
101570 zDfltColl = pParent->aCol[iCol].zColl;
101571 if( !zDfltColl ){
101572 zDfltColl = "BINARY";
101573 }
101574 if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break;
101575
101576 zIdxCol = pParent->aCol[iCol].zName;
101577 for(j=0; j<nCol; j++){
101578 if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){
@@ -104430,24 +104442,10 @@
104430 SQLITE_API int sqlite3_xferopt_count;
104431 #endif /* SQLITE_TEST */
104432
104433
104434 #ifndef SQLITE_OMIT_XFER_OPT
104435 /*
104436 ** Check to collation names to see if they are compatible.
104437 */
104438 static int xferCompatibleCollation(const char *z1, const char *z2){
104439 if( z1==0 ){
104440 return z2==0;
104441 }
104442 if( z2==0 ){
104443 return 0;
104444 }
104445 return sqlite3StrICmp(z1, z2)==0;
104446 }
104447
104448
104449 /*
104450 ** Check to see if index pSrc is compatible as a source of data
104451 ** for index pDest in an insert transfer optimization. The rules
104452 ** for a compatible index:
104453 **
@@ -104479,11 +104477,11 @@
104479 }
104480 }
104481 if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){
104482 return 0; /* Different sort orders */
104483 }
104484 if( !xferCompatibleCollation(pSrc->azColl[i],pDest->azColl[i]) ){
104485 return 0; /* Different collating sequences */
104486 }
104487 }
104488 if( sqlite3ExprCompare(pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){
104489 return 0; /* Different WHERE clauses */
@@ -104640,11 +104638,11 @@
104640 }
104641 #endif
104642 if( pDestCol->affinity!=pSrcCol->affinity ){
104643 return 0; /* Affinity must be the same on all columns */
104644 }
104645 if( !xferCompatibleCollation(pDestCol->zColl, pSrcCol->zColl) ){
104646 return 0; /* Collating sequence must be the same on all columns */
104647 }
104648 if( pDestCol->notNull && !pSrcCol->notNull ){
104649 return 0; /* tab2 must be NOT NULL if tab1 is */
104650 }
@@ -104787,13 +104785,14 @@
104787 ** BINARY, this optimization is disabled. This is because the user
104788 ** might change the definition of a collation sequence and then run
104789 ** a VACUUM command. In that case keys may not be written in strictly
104790 ** sorted order. */
104791 for(i=0; i<pSrcIdx->nColumn; i++){
104792 char *zColl = pSrcIdx->azColl[i];
104793 assert( zColl!=0 );
104794 if( sqlite3_stricmp("BINARY", zColl) ) break;
 
104795 }
104796 if( i==pSrcIdx->nColumn ){
104797 idxInsFlags = OPFLAG_USESEEKRESULT;
104798 sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1);
104799 }
@@ -119290,11 +119289,11 @@
119290 ** terms in the WHERE clause that are useful to the query planner.
119291 */
119292 struct WhereScan {
119293 WhereClause *pOrigWC; /* Original, innermost WhereClause */
119294 WhereClause *pWC; /* WhereClause currently being scanned */
119295 char *zCollName; /* Required collating sequence, if not NULL */
119296 Expr *pIdxExpr; /* Search for this index expression */
119297 char idxaff; /* Must match this affinity, if zCollName!=NULL */
119298 unsigned char nEquiv; /* Number of entries in aEquiv[] */
119299 unsigned char iEquiv; /* Next unused slot in aEquiv[] */
119300 u32 opMask; /* Acceptable operators */
@@ -123276,11 +123275,11 @@
123276 if( (idxCols & cMask)==0 ){
123277 Expr *pX = pTerm->pExpr;
123278 idxCols |= cMask;
123279 pIdx->aiColumn[n] = pTerm->u.leftColumn;
123280 pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
123281 pIdx->azColl[n] = pColl ? pColl->zName : "BINARY";
123282 n++;
123283 }
123284 }
123285 }
123286 assert( (u32)n==pLoop->u.btree.nEq );
@@ -123288,24 +123287,24 @@
123288 /* Add additional columns needed to make the automatic index into
123289 ** a covering index */
123290 for(i=0; i<mxBitCol; i++){
123291 if( extraCols & MASKBIT(i) ){
123292 pIdx->aiColumn[n] = i;
123293 pIdx->azColl[n] = "BINARY";
123294 n++;
123295 }
123296 }
123297 if( pSrc->colUsed & MASKBIT(BMS-1) ){
123298 for(i=BMS-1; i<pTable->nCol; i++){
123299 pIdx->aiColumn[n] = i;
123300 pIdx->azColl[n] = "BINARY";
123301 n++;
123302 }
123303 }
123304 assert( n==nKeyCol );
123305 pIdx->aiColumn[n] = XN_ROWID;
123306 pIdx->azColl[n] = "BINARY";
123307
123308 /* Create the automatic index */
123309 assert( pLevel->iIdxCur>=0 );
123310 pLevel->iIdxCur = pParse->nTab++;
123311 sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1);
@@ -134856,22 +134855,22 @@
134856 ** conversions. The only error that can occur here is a malloc() failure.
134857 **
134858 ** EVIDENCE-OF: R-52786-44878 SQLite defines three built-in collating
134859 ** functions:
134860 */
134861 createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0);
134862 createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0);
134863 createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0);
134864 createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0);
134865 createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0);
134866 if( db->mallocFailed ){
134867 goto opendb_out;
134868 }
134869 /* EVIDENCE-OF: R-08308-17224 The default collating function for all
134870 ** strings is BINARY.
134871 */
134872 db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0);
134873 assert( db->pDfltColl!=0 );
134874
134875 /* Parse the filename/URI argument. */
134876 db->openFlags = flags;
134877 rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
@@ -135367,11 +135366,11 @@
135367 }else{
135368 zDataType = "INTEGER";
135369 primarykey = 1;
135370 }
135371 if( !zCollSeq ){
135372 zCollSeq = "BINARY";
135373 }
135374
135375 error_out:
135376 sqlite3BtreeLeaveAll(db);
135377
@@ -135975,11 +135974,10 @@
135975 */
135976 SQLITE_API void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){
135977 sqlite3_free(pSnapshot);
135978 }
135979 #endif /* SQLITE_ENABLE_SNAPSHOT */
135980
135981
135982 /************** End of main.c ************************************************/
135983 /************** Begin file notify.c ******************************************/
135984 /*
135985 ** 2009 March 3
@@ -166096,11 +166094,11 @@
166096 sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE);
166097 }
166098 #endif /* SQLITE_DEBUG */
166099
166100 /****************************************************************************
166101 ** SQL function implementations
166102 ****************************************************************************/
166103
166104 /*
166105 ** Implementation of the json_array(VALUE,...) function. Return a JSON
166106 ** array that contains all values given in arguments. Or if any argument
@@ -166428,10 +166426,106 @@
166428 rc = 1;
166429 }
166430 jsonParseReset(&x);
166431 sqlite3_result_int(ctx, rc);
166432 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166433
166434 #ifndef SQLITE_OMIT_VIRTUALTABLE
166435 /****************************************************************************
166436 ** The json_each virtual table
166437 ****************************************************************************/
@@ -166927,10 +167021,19 @@
166927 /* DEBUG and TESTING functions */
166928 { "json_parse", 1, 0, jsonParseFunc },
166929 { "json_test1", 1, 0, jsonTest1Func },
166930 #endif
166931 };
 
 
 
 
 
 
 
 
 
166932 #ifndef SQLITE_OMIT_VIRTUALTABLE
166933 static const struct {
166934 const char *zName;
166935 sqlite3_module *pModule;
166936 } aMod[] = {
@@ -166942,10 +167045,15 @@
166942 rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
166943 SQLITE_UTF8 | SQLITE_DETERMINISTIC,
166944 (void*)&aFunc[i].flag,
166945 aFunc[i].xFunc, 0, 0);
166946 }
 
 
 
 
 
166947 #ifndef SQLITE_OMIT_VIRTUALTABLE
166948 for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){
166949 rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0);
166950 }
166951 #endif
@@ -169981,11 +170089,11 @@
169981 { "bm25", 0, fts5Bm25Function, 0 },
169982 };
169983 int rc = SQLITE_OK; /* Return code */
169984 int i; /* To iterate through builtin functions */
169985
169986 for(i=0; rc==SQLITE_OK && i<sizeof(aBuiltin)/sizeof(aBuiltin[0]); i++){
169987 rc = pApi->xCreateFunction(pApi,
169988 aBuiltin[i].zFunc,
169989 aBuiltin[i].pUserData,
169990 aBuiltin[i].xFunc,
169991 aBuiltin[i].xDestroy
@@ -171605,11 +171713,11 @@
171605
171606 fts5BufferZero(&pPhrase->poslist);
171607
171608 /* If the aStatic[] array is not large enough, allocate a large array
171609 ** using sqlite3_malloc(). This approach could be improved upon. */
171610 if( pPhrase->nTerm>(sizeof(aStatic) / sizeof(aStatic[0])) ){
171611 int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
171612 aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte);
171613 if( !aIter ) return SQLITE_NOMEM;
171614 }
171615 memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm);
@@ -171741,11 +171849,11 @@
171741
171742 assert( pNear->nPhrase>1 );
171743
171744 /* If the aStatic[] array is not large enough, allocate a large array
171745 ** using sqlite3_malloc(). This approach could be improved upon. */
171746 if( pNear->nPhrase>(sizeof(aStatic) / sizeof(aStatic[0])) ){
171747 int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
171748 a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte);
171749 }else{
171750 memset(aStatic, 0, sizeof(aStatic));
171751 }
@@ -173388,11 +173496,11 @@
173388 };
173389 int i;
173390 int rc = SQLITE_OK;
173391 void *pCtx = (void*)pGlobal;
173392
173393 for(i=0; rc==SQLITE_OK && i<(sizeof(aFunc) / sizeof(aFunc[0])); i++){
173394 struct Fts5ExprFunc *p = &aFunc[i];
173395 rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
173396 }
173397
173398 /* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */
@@ -180242,11 +180350,11 @@
180242
180243 /* Set idxFlags flags for all WHERE clause terms that will be used. */
180244 for(i=0; i<pInfo->nConstraint; i++){
180245 struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
180246 int j;
180247 for(j=0; j<sizeof(aConstraint)/sizeof(aConstraint[0]); j++){
180248 struct Constraint *pC = &aConstraint[j];
180249 if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){
180250 if( p->usable ){
180251 pC->iConsIndex = i;
180252 idxFlags |= pC->fts5op;
@@ -180289,11 +180397,11 @@
180289 pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0;
180290 }
180291
180292 /* Assign argvIndex values to each constraint in use. */
180293 iNext = 1;
180294 for(i=0; i<sizeof(aConstraint)/sizeof(aConstraint[0]); i++){
180295 struct Constraint *pC = &aConstraint[i];
180296 if( pC->iConsIndex>=0 ){
180297 pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++;
180298 pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit;
180299 }
@@ -182139,11 +182247,11 @@
182139 sqlite3_context *pCtx, /* Function call context */
182140 int nArg, /* Number of args */
182141 sqlite3_value **apVal /* Function arguments */
182142 ){
182143 assert( nArg==0 );
182144 sqlite3_result_text(pCtx, "fts5: 2015-12-18 16:29:47 8bf5e056eb8beb6e0ed5874fb24d7fe9f0b66d2b", -1, SQLITE_TRANSIENT);
182145 }
182146
182147 static int fts5Init(sqlite3 *db){
182148 static const sqlite3_module fts5Mod = {
182149 /* iVersion */ 2,
@@ -182584,11 +182692,11 @@
182584 int rc = SQLITE_OK;
182585 if( p ){
182586 int i;
182587
182588 /* Finalize all SQL statements */
182589 for(i=0; i<ArraySize(p->aStmt); i++){
182590 sqlite3_finalize(p->aStmt[i]);
182591 }
182592
182593 sqlite3_free(p);
182594 }
@@ -184570,11 +184678,11 @@
184570 };
184571
184572 int rc = SQLITE_OK; /* Return code */
184573 int i; /* To iterate through builtin functions */
184574
184575 for(i=0; rc==SQLITE_OK && i<sizeof(aBuiltin)/sizeof(aBuiltin[0]); i++){
184576 rc = pApi->xCreateTokenizer(pApi,
184577 aBuiltin[i].zName,
184578 (void*)pApi,
184579 &aBuiltin[i].x,
184580 0
184581
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -325,11 +325,11 @@
325 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
326 ** [sqlite_version()] and [sqlite_source_id()].
327 */
328 #define SQLITE_VERSION "3.10.0"
329 #define SQLITE_VERSION_NUMBER 3010000
330 #define SQLITE_SOURCE_ID "2016-01-06 11:01:07 fd0a50f0797d154fefff724624f00548b5320566"
331
332 /*
333 ** CAPI3REF: Run-Time Library Version Numbers
334 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
335 **
@@ -9901,15 +9901,10 @@
9901 ** For best performance, an attempt is made to guess at the byte-order
9902 ** using C-preprocessor macros. If that is unsuccessful, or if
9903 ** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
9904 ** at run-time.
9905 */
 
 
 
 
 
9906 #if (defined(i386) || defined(__i386__) || defined(_M_IX86) || \
9907 defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
9908 defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
9909 defined(__arm__)) && !defined(SQLITE_RUNTIME_BYTEORDER)
9910 # define SQLITE_BYTEORDER 1234
@@ -9923,10 +9918,15 @@
9918 # define SQLITE_BIGENDIAN 1
9919 # define SQLITE_LITTLEENDIAN 0
9920 # define SQLITE_UTF16NATIVE SQLITE_UTF16BE
9921 #endif
9922 #if !defined(SQLITE_BYTEORDER)
9923 # ifdef SQLITE_AMALGAMATION
9924 const int sqlite3one = 1;
9925 # else
9926 extern const int sqlite3one;
9927 # endif
9928 # define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */
9929 # define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
9930 # define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
9931 # define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
9932 #endif
@@ -12317,11 +12317,11 @@
12317 char *zDflt; /* Original text of the default value */
12318 char *zType; /* Data type for this column */
12319 char *zColl; /* Collating sequence. If NULL, use the default */
12320 u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
12321 char affinity; /* One of the SQLITE_AFF_... values */
12322 u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */
12323 u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */
12324 };
12325
12326 /* Allowed values for Column.colFlags:
12327 */
@@ -12727,11 +12727,11 @@
12727 Table *pTable; /* The SQL table being indexed */
12728 char *zColAff; /* String defining the affinity of each column */
12729 Index *pNext; /* The next index associated with the same table */
12730 Schema *pSchema; /* Schema containing this index */
12731 u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
12732 const char **azColl; /* Array of collation sequence names for index */
12733 Expr *pPartIdxWhere; /* WHERE clause for partial indices */
12734 ExprList *aColExpr; /* Column expressions */
12735 int tnum; /* DB Page containing root of this index */
12736 LogEst szIdxRow; /* Estimated average row size in bytes */
12737 u16 nKeyCol; /* Number of columns forming the key */
@@ -13527,10 +13527,11 @@
13527 int nTab; /* Number of previously allocated VDBE cursors */
13528 int nMem; /* Number of memory cells used so far */
13529 int nSet; /* Number of sets used so far */
13530 int nOnce; /* Number of OP_Once instructions so far */
13531 int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
13532 int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
13533 int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */
13534 int ckBase; /* Base register of data during check constraints */
13535 int iSelfTab; /* Table of an index whose exprs are being coded */
13536 int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
13537 int iCacheCnt; /* Counter used to generate aColCache[].lru values */
@@ -13758,13 +13759,13 @@
13759 */
13760 struct StrAccum {
13761 sqlite3 *db; /* Optional database for lookaside. Can be NULL */
13762 char *zBase; /* A base allocation. Not from malloc. */
13763 char *zText; /* The string collected so far */
13764 u32 nChar; /* Length of the string so far */
13765 u32 nAlloc; /* Amount of space allocated in zText */
13766 u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */
13767 u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
13768 u8 bMalloced; /* zText points to allocated space */
13769 };
13770 #define STRACCUM_NOMEM 1
13771 #define STRACCUM_TOOBIG 2
@@ -14143,11 +14144,15 @@
14144 SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
14145 SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
14146 SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*);
14147 SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index*, i16);
14148 SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
14149 #if SQLITE_ENABLE_HIDDEN_COLUMNS
14150 SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*);
14151 #else
14152 # define sqlite3ColumnPropertiesFromName(T,C) /* no-op */
14153 #endif
14154 SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*);
14155 SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
14156 SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
14157 SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
14158 SQLITE_PRIVATE void sqlite3AddColumnType(Parse*,Token*);
@@ -14494,10 +14499,11 @@
14499 SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
14500 SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
14501 SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
14502 #ifndef SQLITE_AMALGAMATION
14503 SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[];
14504 SQLITE_PRIVATE const char sqlite3StrBINARY[];
14505 SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
14506 SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[];
14507 SQLITE_PRIVATE const Token sqlite3IntTokens[];
14508 SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config;
14509 SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
@@ -15099,10 +15105,15 @@
15105 ** from the comments following the "case OP_xxxx:" statements in
15106 ** the vdbe.c file.
15107 */
15108 SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
15109
15110 /*
15111 ** Name of the default collating sequence
15112 */
15113 SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY";
15114
15115 /************** End of global.c **********************************************/
15116 /************** Begin file ctime.c *******************************************/
15117 /*
15118 ** 2010 February 23
15119 **
@@ -20655,10 +20666,12 @@
20666 int trace; /* True to trace changes */
20667 #endif
20668 };
20669 #if SQLITE_MUTEX_NREF
20670 #define SQLITE3_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,0,0,(pthread_t)0,0}
20671 #elif defined(SQLITE_ENABLE_API_ARMOR)
20672 #define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0 }
20673 #else
20674 #define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
20675 #endif
20676
20677 /*
@@ -24490,17 +24503,17 @@
24503 */
24504 /* #include "sqliteInt.h" */
24505 /* #include <assert.h> */
24506 /* #include "vdbeInt.h" */
24507
24508 #if !defined(SQLITE_AMALGAMATION) && SQLITE_BYTEORDER==0
24509 /*
24510 ** The following constant value is used by the SQLITE_BIGENDIAN and
24511 ** SQLITE_LITTLEENDIAN macros.
24512 */
24513 SQLITE_PRIVATE const int sqlite3one = 1;
24514 #endif /* SQLITE_AMALGAMATION && SQLITE_BYTEORDER==0 */
24515
24516 /*
24517 ** This lookup table is used to help decode the first byte of
24518 ** a multi-byte UTF8 character.
24519 */
@@ -54549,11 +54562,10 @@
54562 struct CellInfo {
54563 i64 nKey; /* The key for INTKEY tables, or nPayload otherwise */
54564 u8 *pPayload; /* Pointer to the start of payload */
54565 u32 nPayload; /* Bytes of payload */
54566 u16 nLocal; /* Amount of payload held locally, not on overflow */
 
54567 u16 nSize; /* Size of the cell content on the main b-tree page */
54568 };
54569
54570 /*
54571 ** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than
@@ -56130,12 +56142,11 @@
56142 if( surplus <= maxLocal ){
56143 pInfo->nLocal = (u16)surplus;
56144 }else{
56145 pInfo->nLocal = (u16)minLocal;
56146 }
56147 pInfo->nSize = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell) + 4;
 
56148 }
56149
56150 /*
56151 ** The following routines are implementations of the MemPage.xParseCell()
56152 ** method.
@@ -56163,11 +56174,10 @@
56174 UNUSED_PARAMETER(pPage);
56175 #endif
56176 pInfo->nSize = 4 + getVarint(&pCell[4], (u64*)&pInfo->nKey);
56177 pInfo->nPayload = 0;
56178 pInfo->nLocal = 0;
 
56179 pInfo->pPayload = 0;
56180 return;
56181 }
56182 static void btreeParseCellPtr(
56183 MemPage *pPage, /* Page containing the cell */
@@ -56233,11 +56243,10 @@
56243 ** on the local page. No overflow is required.
56244 */
56245 pInfo->nSize = nPayload + (u16)(pIter - pCell);
56246 if( pInfo->nSize<4 ) pInfo->nSize = 4;
56247 pInfo->nLocal = (u16)nPayload;
 
56248 }else{
56249 btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo);
56250 }
56251 }
56252 static void btreeParseCellPtrIndex(
@@ -56272,11 +56281,10 @@
56281 ** on the local page. No overflow is required.
56282 */
56283 pInfo->nSize = nPayload + (u16)(pIter - pCell);
56284 if( pInfo->nSize<4 ) pInfo->nSize = 4;
56285 pInfo->nLocal = (u16)nPayload;
 
56286 }else{
56287 btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo);
56288 }
56289 }
56290 static void btreeParseCell(
@@ -56388,12 +56396,12 @@
56396 static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
56397 CellInfo info;
56398 if( *pRC ) return;
56399 assert( pCell!=0 );
56400 pPage->xParseCell(pPage, pCell, &info);
56401 if( info.nLocal<info.nPayload ){
56402 Pgno ovfl = get4byte(&pCell[info.nSize-4]);
56403 ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC);
56404 }
56405 }
56406 #endif
56407
@@ -58427,15 +58435,15 @@
58435 for(i=0; i<nCell; i++){
58436 u8 *pCell = findCell(pPage, i);
58437 if( eType==PTRMAP_OVERFLOW1 ){
58438 CellInfo info;
58439 pPage->xParseCell(pPage, pCell, &info);
58440 if( info.nLocal<info.nPayload
58441 && pCell+info.nSize-1<=pPage->aData+pPage->maskPage
58442 && iFrom==get4byte(pCell+info.nSize-4)
58443 ){
58444 put4byte(pCell+info.nSize-4, iTo);
58445 break;
58446 }
58447 }else{
58448 if( get4byte(pCell)==iFrom ){
58449 put4byte(pCell, iTo);
@@ -61073,17 +61081,17 @@
61081 u32 ovflPageSize;
61082
61083 assert( sqlite3_mutex_held(pPage->pBt->mutex) );
61084 pPage->xParseCell(pPage, pCell, &info);
61085 *pnSize = info.nSize;
61086 if( info.nLocal==info.nPayload ){
61087 return SQLITE_OK; /* No overflow pages. Return without doing anything */
61088 }
61089 if( pCell+info.nSize-1 > pPage->aData+pPage->maskPage ){
61090 return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */
61091 }
61092 ovflPgno = get4byte(pCell + info.nSize - 4);
61093 assert( pBt->usableSize > 4 );
61094 ovflPageSize = pBt->usableSize - 4;
61095 nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
61096 assert( nOvfl>0 ||
61097 (CORRUPT_DB && (info.nPayload + ovflPageSize)<ovflPageSize)
@@ -61228,11 +61236,10 @@
61236 pPage->xParseCell(pPage, pCell, &info);
61237 assert( nHeader=(int)(info.pPayload - pCell) );
61238 assert( info.nKey==nKey );
61239 assert( *pnSize == info.nSize );
61240 assert( spaceLeft == info.nLocal );
 
61241 }
61242 #endif
61243
61244 /* Write the payload into the local Cell and any extra into overflow pages */
61245 while( nPayload>0 ){
@@ -61938,12 +61945,12 @@
61945 CellInfo info;
61946 u8 *z;
61947
61948 z = findCell(pPage, j);
61949 pPage->xParseCell(pPage, z, &info);
61950 if( info.nLocal<info.nPayload ){
61951 Pgno ovfl = get4byte(&z[info.nSize-4]);
61952 ptrmapGet(pBt, ovfl, &e, &n);
61953 assert( n==pPage->pgno && e==PTRMAP_OVERFLOW1 );
61954 }
61955 if( !pPage->leaf ){
61956 Pgno child = get4byte(z);
@@ -63305,11 +63312,11 @@
63312 rc = balance(pCur);
63313 }
63314
63315 if( rc==SQLITE_OK ){
63316 if( bSkipnext ){
63317 assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) );
63318 assert( pPage==pCur->apPage[pCur->iPage] );
63319 assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell );
63320 pCur->eState = CURSOR_SKIPNEXT;
63321 if( iCellIdx>=pPage->nCell ){
63322 pCur->skipNext = -1;
@@ -64245,13 +64252,13 @@
64252
64253 /* Check the content overflow list */
64254 if( info.nPayload>info.nLocal ){
64255 int nPage; /* Number of pages on the overflow chain */
64256 Pgno pgnoOvfl; /* First page of the overflow chain */
64257 assert( pc + info.nSize - 4 <= usableSize );
64258 nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
64259 pgnoOvfl = get4byte(&pCell[info.nSize - 4]);
64260 #ifndef SQLITE_OMIT_AUTOVACUUM
64261 if( pBt->autoVacuum ){
64262 checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage);
64263 }
64264 #endif
@@ -67316,10 +67323,11 @@
67323 p->magic = VDBE_MAGIC_INIT;
67324 p->pParse = pParse;
67325 assert( pParse->aLabel==0 );
67326 assert( pParse->nLabel==0 );
67327 assert( pParse->nOpAlloc==0 );
67328 assert( pParse->szOpAlloc==0 );
67329 return p;
67330 }
67331
67332 /*
67333 ** Change the error string stored in Vdbe.zErrMsg
@@ -67405,11 +67413,12 @@
67413
67414 assert( nOp<=(1024/sizeof(Op)) );
67415 assert( nNew>=(p->nOpAlloc+nOp) );
67416 pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
67417 if( pNew ){
67418 p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew);
67419 p->nOpAlloc = p->szOpAlloc/sizeof(Op);
67420 v->aOp = pNew;
67421 }
67422 return (pNew ? SQLITE_OK : SQLITE_NOMEM);
67423 }
67424
@@ -69127,24 +69136,31 @@
69136 **
69137 ** See also: allocateCursor().
69138 */
69139 nMem += nCursor;
69140
69141 /* zCsr will initially point to nFree bytes of unused space at the
69142 ** end of the opcode array, p->aOp. The computation of nFree is
69143 ** conservative - it might be smaller than the true number of free
69144 ** bytes, but never larger. nFree must be a multiple of 8 - it is
69145 ** rounded down if is not.
69146 */
69147 n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode space used */
69148 zCsr = &((u8*)p->aOp)[n]; /* Unused opcode space */
69149 assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
69150 nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused space */
69151 assert( nFree>=0 );
69152 if( nFree>0 ){
69153 memset(zCsr, 0, nFree);
69154 assert( EIGHT_BYTE_ALIGNMENT(&zCsr[nFree]) );
69155 }
69156
69157 resolveP2Values(p, &nArg);
69158 p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
69159 if( pParse->explain && nMem<10 ){
69160 nMem = 10;
69161 }
 
 
69162 p->expired = 0;
69163
69164 /* Memory for registers, parameters, cursor, etc, is allocated in two
69165 ** passes. On the first pass, we try to reuse unused space at the
69166 ** end of the opcode array. If we are unable to satisfy all memory
@@ -71029,11 +71045,11 @@
71045 }
71046 if( (f2 & MEM_Str)==0 ){
71047 return -1;
71048 }
71049
71050 assert( pMem1->enc==pMem2->enc || pMem1->db->mallocFailed );
71051 assert( pMem1->enc==SQLITE_UTF8 ||
71052 pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
71053
71054 /* The collation sequence must be defined at this point, even if
71055 ** the user deletes the collation sequence after the vdbe program is
@@ -75665,42 +75681,41 @@
75681 }
75682 }else{
75683 /* Neither operand is NULL. Do a comparison. */
75684 affinity = pOp->p5 & SQLITE_AFF_MASK;
75685 if( affinity>=SQLITE_AFF_NUMERIC ){
75686 if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
75687 applyNumericAffinity(pIn1,0);
75688 }
75689 if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
75690 applyNumericAffinity(pIn3,0);
75691 }
75692 }else if( affinity==SQLITE_AFF_TEXT ){
75693 if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){
75694 testcase( pIn1->flags & MEM_Int );
75695 testcase( pIn1->flags & MEM_Real );
75696 sqlite3VdbeMemStringify(pIn1, encoding, 1);
75697 testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
75698 flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
75699 }
75700 if( (flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0 ){
75701 testcase( pIn3->flags & MEM_Int );
75702 testcase( pIn3->flags & MEM_Real );
75703 sqlite3VdbeMemStringify(pIn3, encoding, 1);
75704 testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
75705 flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
75706 }
75707 }
75708 assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
75709 if( flags1 & MEM_Zero ){
75710 sqlite3VdbeMemExpandBlob(pIn1);
75711 flags1 &= ~MEM_Zero;
75712 }
75713 if( flags3 & MEM_Zero ){
75714 sqlite3VdbeMemExpandBlob(pIn3);
75715 flags3 &= ~MEM_Zero;
75716 }
 
75717 res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
75718 }
75719 switch( pOp->opcode ){
75720 case OP_Eq: res = res==0; break;
75721 case OP_Ne: res = res!=0; break;
@@ -76194,11 +76209,11 @@
76209 ){
76210 rc = SQLITE_CORRUPT_BKPT;
76211 goto op_column_error;
76212 }
76213 }else{
76214 t = 0;
76215 }
76216
76217 /* If after trying to extract new entries from the header, nHdrParsed is
76218 ** still not up to p2, that means that the record has fewer than p2
76219 ** columns. So the result will be either the default value or a NULL.
@@ -77072,11 +77087,11 @@
77087
77088 open_cursor_set_hints:
77089 assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
77090 assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
77091 testcase( pOp->p5 & OPFLAG_BULKCSR );
77092 #ifdef SQLITE_ENABLE_CURSOR_HINTS
77093 testcase( pOp->p2 & OPFLAG_SEEKEQ );
77094 #endif
77095 sqlite3BtreeCursorHintFlags(pCur->uc.pCursor,
77096 (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
77097 break;
@@ -86739,11 +86754,11 @@
86754 }
86755 if( isReduced ){
86756 assert( ExprHasProperty(p, EP_Reduced)==0 );
86757 memcpy(zAlloc, p, nNewSize);
86758 }else{
86759 u32 nSize = (u32)exprStructSize(p);
86760 memcpy(zAlloc, p, nSize);
86761 if( nSize<EXPR_FULLSIZE ){
86762 memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
86763 }
86764 }
@@ -94128,11 +94143,11 @@
94143 sqlite3DeleteIndexSamples(db, p);
94144 #endif
94145 sqlite3ExprDelete(db, p->pPartIdxWhere);
94146 sqlite3ExprListDelete(db, p->aColExpr);
94147 sqlite3DbFree(db, p->zColAff);
94148 if( p->isResized ) sqlite3DbFree(db, (void *)p->azColl);
94149 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
94150 sqlite3_free(p->aiRowEst);
94151 #endif
94152 sqlite3DbFree(db, p);
94153 }
@@ -94731,19 +94746,19 @@
94746 }
94747
94748 /* Set properties of a table column based on the (magical)
94749 ** name of the column.
94750 */
 
94751 #if SQLITE_ENABLE_HIDDEN_COLUMNS
94752 SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
94753 if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){
94754 pCol->colFlags |= COLFLAG_HIDDEN;
94755 }else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){
94756 pTab->tabFlags |= TF_OOOHidden;
94757 }
94758 }
94759 #endif
 
94760
94761
94762 /*
94763 ** Add a new column to the table currently being constructed.
94764 **
@@ -95319,11 +95334,11 @@
95334 assert( pIdx->isResized==0 );
95335 nByte = (sizeof(char*) + sizeof(i16) + 1)*N;
95336 zExtra = sqlite3DbMallocZero(db, nByte);
95337 if( zExtra==0 ) return SQLITE_NOMEM;
95338 memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
95339 pIdx->azColl = (const char**)zExtra;
95340 zExtra += sizeof(char*)*N;
95341 memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn);
95342 pIdx->aiColumn = (i16*)zExtra;
95343 zExtra += sizeof(i16)*N;
95344 memcpy(zExtra, pIdx->aSortOrder, pIdx->nColumn);
@@ -95458,11 +95473,11 @@
95473
95474 /* Make sure every column of the PRIMARY KEY is NOT NULL. (Except,
95475 ** do not enforce this for imposter tables.) */
95476 if( !db->init.imposterTable ){
95477 for(i=0; i<nPk; i++){
95478 pTab->aCol[pPk->aiColumn[i]].notNull = OE_Abort;
95479 }
95480 pPk->uniqNotNull = 1;
95481 }
95482
95483 /* The root page of the PRIMARY KEY is the table root page */
@@ -95500,11 +95515,11 @@
95515 if( resizeIndexObject(db, pPk, pTab->nCol) ) return;
95516 for(i=0, j=nPk; i<pTab->nCol; i++){
95517 if( !hasColumn(pPk->aiColumn, j, i) ){
95518 assert( j<pPk->nColumn );
95519 pPk->aiColumn[j] = i;
95520 pPk->azColl[j] = sqlite3StrBINARY;
95521 j++;
95522 }
95523 }
95524 assert( pPk->nColumn==j );
95525 assert( pTab->nCol==j );
@@ -96550,11 +96565,11 @@
96565 sizeof(i16)*nCol + /* Index.aiColumn */
96566 sizeof(u8)*nCol); /* Index.aSortOrder */
96567 p = sqlite3DbMallocZero(db, nByte + nExtra);
96568 if( p ){
96569 char *pExtra = ((char*)p)+ROUND8(sizeof(Index));
96570 p->azColl = (const char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol);
96571 p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1);
96572 p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol;
96573 p->aSortOrder = (u8*)pExtra;
96574 p->nColumn = nCol;
96575 p->nKeyCol = nCol - 1;
@@ -96827,11 +96842,11 @@
96842 ** index key.
96843 */
96844 for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
96845 Expr *pCExpr; /* The i-th index expression */
96846 int requestedSortOrder; /* ASC or DESC on the i-th expression */
96847 const char *zColl; /* Collation sequence name */
96848
96849 sqlite3StringToId(pListItem->pExpr);
96850 sqlite3ResolveSelfReference(pParse, pTab, NC_IdxExpr, pListItem->pExpr, 0);
96851 if( pParse->nErr ) goto exit_create_index;
96852 pCExpr = sqlite3ExprSkipCollate(pListItem->pExpr);
@@ -96873,11 +96888,11 @@
96888 zExtra += nColl;
96889 nExtra -= nColl;
96890 }else if( j>=0 ){
96891 zColl = pTab->aCol[j].zColl;
96892 }
96893 if( !zColl ) zColl = sqlite3StrBINARY;
96894 if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
96895 goto exit_create_index;
96896 }
96897 pIndex->azColl[i] = zColl;
96898 requestedSortOrder = pListItem->sortOrder & sortOrderMask;
@@ -96902,11 +96917,11 @@
96917 }
96918 }
96919 assert( i==pIndex->nColumn );
96920 }else{
96921 pIndex->aiColumn[i] = XN_ROWID;
96922 pIndex->azColl[i] = sqlite3StrBINARY;
96923 }
96924 sqlite3DefaultRowEst(pIndex);
96925 if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);
96926
96927 if( pTab==pParse->pNewTable ){
@@ -98026,13 +98041,12 @@
98041 pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
98042 }
98043 if( pKey ){
98044 assert( sqlite3KeyInfoIsWriteable(pKey) );
98045 for(i=0; i<nCol; i++){
98046 const char *zColl = pIdx->azColl[i];
98047 pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 :
 
98048 sqlite3LocateCollSeq(pParse, zColl);
98049 pKey->aSortOrder[i] = pIdx->aSortOrder[i];
98050 }
98051 if( pParse->nErr ){
98052 sqlite3KeyInfoUnref(pKey);
@@ -100238,11 +100252,11 @@
100252 continue;
100253 }
100254 }
100255 c2 = Utf8Read(zString);
100256 if( c==c2 ) continue;
100257 if( noCase && sqlite3Tolower(c)==sqlite3Tolower(c2) ){
100258 continue;
100259 }
100260 if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue;
100261 return 0;
100262 }
@@ -101557,22 +101571,20 @@
101571 ** index matches those columns. Also, check that the index uses
101572 ** the default collation sequences for each column. */
101573 int i, j;
101574 for(i=0; i<nCol; i++){
101575 i16 iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */
101576 const char *zDfltColl; /* Def. collation for column */
101577 char *zIdxCol; /* Name of indexed column */
101578
101579 if( iCol<0 ) break; /* No foreign keys against expression indexes */
101580
101581 /* If the index uses a collation sequence that is different from
101582 ** the default collation sequence for the column, this index is
101583 ** unusable. Bail out early in this case. */
101584 zDfltColl = pParent->aCol[iCol].zColl;
101585 if( !zDfltColl ) zDfltColl = sqlite3StrBINARY;
 
 
101586 if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break;
101587
101588 zIdxCol = pParent->aCol[iCol].zName;
101589 for(j=0; j<nCol; j++){
101590 if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){
@@ -104430,24 +104442,10 @@
104442 SQLITE_API int sqlite3_xferopt_count;
104443 #endif /* SQLITE_TEST */
104444
104445
104446 #ifndef SQLITE_OMIT_XFER_OPT
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104447 /*
104448 ** Check to see if index pSrc is compatible as a source of data
104449 ** for index pDest in an insert transfer optimization. The rules
104450 ** for a compatible index:
104451 **
@@ -104479,11 +104477,11 @@
104477 }
104478 }
104479 if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){
104480 return 0; /* Different sort orders */
104481 }
104482 if( sqlite3_stricmp(pSrc->azColl[i],pDest->azColl[i])!=0 ){
104483 return 0; /* Different collating sequences */
104484 }
104485 }
104486 if( sqlite3ExprCompare(pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){
104487 return 0; /* Different WHERE clauses */
@@ -104640,11 +104638,11 @@
104638 }
104639 #endif
104640 if( pDestCol->affinity!=pSrcCol->affinity ){
104641 return 0; /* Affinity must be the same on all columns */
104642 }
104643 if( sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl)!=0 ){
104644 return 0; /* Collating sequence must be the same on all columns */
104645 }
104646 if( pDestCol->notNull && !pSrcCol->notNull ){
104647 return 0; /* tab2 must be NOT NULL if tab1 is */
104648 }
@@ -104787,13 +104785,14 @@
104785 ** BINARY, this optimization is disabled. This is because the user
104786 ** might change the definition of a collation sequence and then run
104787 ** a VACUUM command. In that case keys may not be written in strictly
104788 ** sorted order. */
104789 for(i=0; i<pSrcIdx->nColumn; i++){
104790 const char *zColl = pSrcIdx->azColl[i];
104791 assert( sqlite3_stricmp(sqlite3StrBINARY, zColl)!=0
104792 || sqlite3StrBINARY==zColl );
104793 if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
104794 }
104795 if( i==pSrcIdx->nColumn ){
104796 idxInsFlags = OPFLAG_USESEEKRESULT;
104797 sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1);
104798 }
@@ -119290,11 +119289,11 @@
119289 ** terms in the WHERE clause that are useful to the query planner.
119290 */
119291 struct WhereScan {
119292 WhereClause *pOrigWC; /* Original, innermost WhereClause */
119293 WhereClause *pWC; /* WhereClause currently being scanned */
119294 const char *zCollName; /* Required collating sequence, if not NULL */
119295 Expr *pIdxExpr; /* Search for this index expression */
119296 char idxaff; /* Must match this affinity, if zCollName!=NULL */
119297 unsigned char nEquiv; /* Number of entries in aEquiv[] */
119298 unsigned char iEquiv; /* Next unused slot in aEquiv[] */
119299 u32 opMask; /* Acceptable operators */
@@ -123276,11 +123275,11 @@
123275 if( (idxCols & cMask)==0 ){
123276 Expr *pX = pTerm->pExpr;
123277 idxCols |= cMask;
123278 pIdx->aiColumn[n] = pTerm->u.leftColumn;
123279 pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
123280 pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
123281 n++;
123282 }
123283 }
123284 }
123285 assert( (u32)n==pLoop->u.btree.nEq );
@@ -123288,24 +123287,24 @@
123287 /* Add additional columns needed to make the automatic index into
123288 ** a covering index */
123289 for(i=0; i<mxBitCol; i++){
123290 if( extraCols & MASKBIT(i) ){
123291 pIdx->aiColumn[n] = i;
123292 pIdx->azColl[n] = sqlite3StrBINARY;
123293 n++;
123294 }
123295 }
123296 if( pSrc->colUsed & MASKBIT(BMS-1) ){
123297 for(i=BMS-1; i<pTable->nCol; i++){
123298 pIdx->aiColumn[n] = i;
123299 pIdx->azColl[n] = sqlite3StrBINARY;
123300 n++;
123301 }
123302 }
123303 assert( n==nKeyCol );
123304 pIdx->aiColumn[n] = XN_ROWID;
123305 pIdx->azColl[n] = sqlite3StrBINARY;
123306
123307 /* Create the automatic index */
123308 assert( pLevel->iIdxCur>=0 );
123309 pLevel->iIdxCur = pParse->nTab++;
123310 sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1);
@@ -134856,22 +134855,22 @@
134855 ** conversions. The only error that can occur here is a malloc() failure.
134856 **
134857 ** EVIDENCE-OF: R-52786-44878 SQLite defines three built-in collating
134858 ** functions:
134859 */
134860 createCollation(db, sqlite3StrBINARY, SQLITE_UTF8, 0, binCollFunc, 0);
134861 createCollation(db, sqlite3StrBINARY, SQLITE_UTF16BE, 0, binCollFunc, 0);
134862 createCollation(db, sqlite3StrBINARY, SQLITE_UTF16LE, 0, binCollFunc, 0);
134863 createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0);
134864 createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0);
134865 if( db->mallocFailed ){
134866 goto opendb_out;
134867 }
134868 /* EVIDENCE-OF: R-08308-17224 The default collating function for all
134869 ** strings is BINARY.
134870 */
134871 db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, sqlite3StrBINARY, 0);
134872 assert( db->pDfltColl!=0 );
134873
134874 /* Parse the filename/URI argument. */
134875 db->openFlags = flags;
134876 rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
@@ -135367,11 +135366,11 @@
135366 }else{
135367 zDataType = "INTEGER";
135368 primarykey = 1;
135369 }
135370 if( !zCollSeq ){
135371 zCollSeq = sqlite3StrBINARY;
135372 }
135373
135374 error_out:
135375 sqlite3BtreeLeaveAll(db);
135376
@@ -135975,11 +135974,10 @@
135974 */
135975 SQLITE_API void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){
135976 sqlite3_free(pSnapshot);
135977 }
135978 #endif /* SQLITE_ENABLE_SNAPSHOT */
 
135979
135980 /************** End of main.c ************************************************/
135981 /************** Begin file notify.c ******************************************/
135982 /*
135983 ** 2009 March 3
@@ -166096,11 +166094,11 @@
166094 sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE);
166095 }
166096 #endif /* SQLITE_DEBUG */
166097
166098 /****************************************************************************
166099 ** Scalar SQL function implementations
166100 ****************************************************************************/
166101
166102 /*
166103 ** Implementation of the json_array(VALUE,...) function. Return a JSON
166104 ** array that contains all values given in arguments. Or if any argument
@@ -166428,10 +166426,106 @@
166426 rc = 1;
166427 }
166428 jsonParseReset(&x);
166429 sqlite3_result_int(ctx, rc);
166430 }
166431
166432
166433 /****************************************************************************
166434 ** Aggregate SQL function implementations
166435 ****************************************************************************/
166436 /*
166437 ** json_group_array(VALUE)
166438 **
166439 ** Return a JSON array composed of all values in the aggregate.
166440 */
166441 static void jsonArrayStep(
166442 sqlite3_context *ctx,
166443 int argc,
166444 sqlite3_value **argv
166445 ){
166446 JsonString *pStr;
166447 pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
166448 if( pStr ){
166449 if( pStr->zBuf==0 ){
166450 jsonInit(pStr, ctx);
166451 jsonAppendChar(pStr, '[');
166452 }else{
166453 jsonAppendChar(pStr, ',');
166454 pStr->pCtx = ctx;
166455 }
166456 jsonAppendValue(pStr, argv[0]);
166457 }
166458 }
166459 static void jsonArrayFinal(sqlite3_context *ctx){
166460 JsonString *pStr;
166461 pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
166462 if( pStr ){
166463 pStr->pCtx = ctx;
166464 jsonAppendChar(pStr, ']');
166465 if( pStr->bErr ){
166466 sqlite3_result_error_nomem(ctx);
166467 assert( pStr->bStatic );
166468 }else{
166469 sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
166470 pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
166471 pStr->bStatic = 1;
166472 }
166473 }else{
166474 sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
166475 }
166476 sqlite3_result_subtype(ctx, JSON_SUBTYPE);
166477 }
166478
166479 /*
166480 ** json_group_obj(NAME,VALUE)
166481 **
166482 ** Return a JSON object composed of all names and values in the aggregate.
166483 */
166484 static void jsonObjectStep(
166485 sqlite3_context *ctx,
166486 int argc,
166487 sqlite3_value **argv
166488 ){
166489 JsonString *pStr;
166490 const char *z;
166491 u32 n;
166492 pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
166493 if( pStr ){
166494 if( pStr->zBuf==0 ){
166495 jsonInit(pStr, ctx);
166496 jsonAppendChar(pStr, '{');
166497 }else{
166498 jsonAppendChar(pStr, ',');
166499 pStr->pCtx = ctx;
166500 }
166501 z = (const char*)sqlite3_value_text(argv[0]);
166502 n = (u32)sqlite3_value_bytes(argv[0]);
166503 jsonAppendString(pStr, z, n);
166504 jsonAppendChar(pStr, ':');
166505 jsonAppendValue(pStr, argv[1]);
166506 }
166507 }
166508 static void jsonObjectFinal(sqlite3_context *ctx){
166509 JsonString *pStr;
166510 pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
166511 if( pStr ){
166512 jsonAppendChar(pStr, '}');
166513 if( pStr->bErr ){
166514 sqlite3_result_error_nomem(ctx);
166515 assert( pStr->bStatic );
166516 }else{
166517 sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
166518 pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
166519 pStr->bStatic = 1;
166520 }
166521 }else{
166522 sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
166523 }
166524 sqlite3_result_subtype(ctx, JSON_SUBTYPE);
166525 }
166526
166527
166528 #ifndef SQLITE_OMIT_VIRTUALTABLE
166529 /****************************************************************************
166530 ** The json_each virtual table
166531 ****************************************************************************/
@@ -166927,10 +167021,19 @@
167021 /* DEBUG and TESTING functions */
167022 { "json_parse", 1, 0, jsonParseFunc },
167023 { "json_test1", 1, 0, jsonTest1Func },
167024 #endif
167025 };
167026 static const struct {
167027 const char *zName;
167028 int nArg;
167029 void (*xStep)(sqlite3_context*,int,sqlite3_value**);
167030 void (*xFinal)(sqlite3_context*);
167031 } aAgg[] = {
167032 { "json_group_array", 1, jsonArrayStep, jsonArrayFinal },
167033 { "json_group_object", 2, jsonObjectStep, jsonObjectFinal },
167034 };
167035 #ifndef SQLITE_OMIT_VIRTUALTABLE
167036 static const struct {
167037 const char *zName;
167038 sqlite3_module *pModule;
167039 } aMod[] = {
@@ -166942,10 +167045,15 @@
167045 rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
167046 SQLITE_UTF8 | SQLITE_DETERMINISTIC,
167047 (void*)&aFunc[i].flag,
167048 aFunc[i].xFunc, 0, 0);
167049 }
167050 for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
167051 rc = sqlite3_create_function(db, aAgg[i].zName, aAgg[i].nArg,
167052 SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
167053 0, aAgg[i].xStep, aAgg[i].xFinal);
167054 }
167055 #ifndef SQLITE_OMIT_VIRTUALTABLE
167056 for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){
167057 rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0);
167058 }
167059 #endif
@@ -169981,11 +170089,11 @@
170089 { "bm25", 0, fts5Bm25Function, 0 },
170090 };
170091 int rc = SQLITE_OK; /* Return code */
170092 int i; /* To iterate through builtin functions */
170093
170094 for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){
170095 rc = pApi->xCreateFunction(pApi,
170096 aBuiltin[i].zFunc,
170097 aBuiltin[i].pUserData,
170098 aBuiltin[i].xFunc,
170099 aBuiltin[i].xDestroy
@@ -171605,11 +171713,11 @@
171713
171714 fts5BufferZero(&pPhrase->poslist);
171715
171716 /* If the aStatic[] array is not large enough, allocate a large array
171717 ** using sqlite3_malloc(). This approach could be improved upon. */
171718 if( pPhrase->nTerm>(int)ArraySize(aStatic) ){
171719 int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
171720 aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte);
171721 if( !aIter ) return SQLITE_NOMEM;
171722 }
171723 memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm);
@@ -171741,11 +171849,11 @@
171849
171850 assert( pNear->nPhrase>1 );
171851
171852 /* If the aStatic[] array is not large enough, allocate a large array
171853 ** using sqlite3_malloc(). This approach could be improved upon. */
171854 if( pNear->nPhrase>(int)ArraySize(aStatic) ){
171855 int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
171856 a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte);
171857 }else{
171858 memset(aStatic, 0, sizeof(aStatic));
171859 }
@@ -173388,11 +173496,11 @@
173496 };
173497 int i;
173498 int rc = SQLITE_OK;
173499 void *pCtx = (void*)pGlobal;
173500
173501 for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aFunc); i++){
173502 struct Fts5ExprFunc *p = &aFunc[i];
173503 rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
173504 }
173505
173506 /* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */
@@ -180242,11 +180350,11 @@
180350
180351 /* Set idxFlags flags for all WHERE clause terms that will be used. */
180352 for(i=0; i<pInfo->nConstraint; i++){
180353 struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
180354 int j;
180355 for(j=0; j<(int)ArraySize(aConstraint); j++){
180356 struct Constraint *pC = &aConstraint[j];
180357 if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){
180358 if( p->usable ){
180359 pC->iConsIndex = i;
180360 idxFlags |= pC->fts5op;
@@ -180289,11 +180397,11 @@
180397 pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0;
180398 }
180399
180400 /* Assign argvIndex values to each constraint in use. */
180401 iNext = 1;
180402 for(i=0; i<(int)ArraySize(aConstraint); i++){
180403 struct Constraint *pC = &aConstraint[i];
180404 if( pC->iConsIndex>=0 ){
180405 pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++;
180406 pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit;
180407 }
@@ -182139,11 +182247,11 @@
182247 sqlite3_context *pCtx, /* Function call context */
182248 int nArg, /* Number of args */
182249 sqlite3_value **apVal /* Function arguments */
182250 ){
182251 assert( nArg==0 );
182252 sqlite3_result_text(pCtx, "fts5: 2016-01-06 11:01:07 fd0a50f0797d154fefff724624f00548b5320566", -1, SQLITE_TRANSIENT);
182253 }
182254
182255 static int fts5Init(sqlite3 *db){
182256 static const sqlite3_module fts5Mod = {
182257 /* iVersion */ 2,
@@ -182584,11 +182692,11 @@
182692 int rc = SQLITE_OK;
182693 if( p ){
182694 int i;
182695
182696 /* Finalize all SQL statements */
182697 for(i=0; i<(int)ArraySize(p->aStmt); i++){
182698 sqlite3_finalize(p->aStmt[i]);
182699 }
182700
182701 sqlite3_free(p);
182702 }
@@ -184570,11 +184678,11 @@
184678 };
184679
184680 int rc = SQLITE_OK; /* Return code */
184681 int i; /* To iterate through builtin functions */
184682
184683 for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){
184684 rc = pApi->xCreateTokenizer(pApi,
184685 aBuiltin[i].zName,
184686 (void*)pApi,
184687 &aBuiltin[i].x,
184688 0
184689
+1 -1
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -111,11 +111,11 @@
111111
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
112112
** [sqlite_version()] and [sqlite_source_id()].
113113
*/
114114
#define SQLITE_VERSION "3.10.0"
115115
#define SQLITE_VERSION_NUMBER 3010000
116
-#define SQLITE_SOURCE_ID "2015-12-23 10:54:48 b910a3d53769689d9212a06f974ccce54844bbe4"
116
+#define SQLITE_SOURCE_ID "2016-01-06 11:01:07 fd0a50f0797d154fefff724624f00548b5320566"
117117
118118
/*
119119
** CAPI3REF: Run-Time Library Version Numbers
120120
** KEYWORDS: sqlite3_version, sqlite3_sourceid
121121
**
122122
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -111,11 +111,11 @@
111 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
112 ** [sqlite_version()] and [sqlite_source_id()].
113 */
114 #define SQLITE_VERSION "3.10.0"
115 #define SQLITE_VERSION_NUMBER 3010000
116 #define SQLITE_SOURCE_ID "2015-12-23 10:54:48 b910a3d53769689d9212a06f974ccce54844bbe4"
117
118 /*
119 ** CAPI3REF: Run-Time Library Version Numbers
120 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
121 **
122
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -111,11 +111,11 @@
111 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
112 ** [sqlite_version()] and [sqlite_source_id()].
113 */
114 #define SQLITE_VERSION "3.10.0"
115 #define SQLITE_VERSION_NUMBER 3010000
116 #define SQLITE_SOURCE_ID "2016-01-06 11:01:07 fd0a50f0797d154fefff724624f00548b5320566"
117
118 /*
119 ** CAPI3REF: Run-Time Library Version Numbers
120 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
121 **
122
--- src/timeline.c
+++ src/timeline.c
@@ -230,18 +230,20 @@
230230
Stmt fchngQuery; /* Query for file changes on check-ins */
231231
static Stmt qbranch;
232232
int pendingEndTr = 0; /* True if a </td></tr> is needed */
233233
int vid = 0; /* Current checkout version */
234234
int dateFormat = 0; /* 0: HH:MM (default) */
235
+ int bCommentGitStyle = 0; /* Only show comments through first blank line */
235236
const char *zDateFmt;
236237
237238
if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){
238239
vid = db_lget_int("checkout", 0);
239240
}
240241
zPrevDate[0] = 0;
241242
mxWikiLen = db_get_int("timeline-max-comment", 0);
242243
dateFormat = db_get_int("timeline-date-format", 0);
244
+ bCommentGitStyle = db_get_int("timeline-truncate-at-blank", 0);
243245
zDateFmt = P("datefmt");
244246
if( zDateFmt ) dateFormat = atoi(zDateFmt);
245247
if( tmFlags & TIMELINE_GRAPH ){
246248
pGraph = graph_init();
247249
}
@@ -434,10 +436,23 @@
434436
db_column_blob(pQuery, commentColumn, &comment);
435437
if( zType[0]!='c' ){
436438
/* Comments for anything other than a check-in are generated by
437439
** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */
438440
wiki_convert(&comment, 0, WIKI_INLINE);
441
+ }else if( bCommentGitStyle ){
442
+ /* Truncate comment at first blank line */
443
+ int ii, jj;
444
+ int n = blob_size(&comment);
445
+ char *z = blob_str(&comment);
446
+ for(ii=0; ii<n; ii++){
447
+ if( z[ii]=='\n' ){
448
+ for(jj=ii+1; jj<n && z[jj]!='\n' && fossil_isspace(z[jj]); jj++){}
449
+ if( z[jj]=='\n' ) break;
450
+ }
451
+ }
452
+ z[ii] = 0;
453
+ @ <span class="timelineComment">%W(z)</span>
439454
}else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
440455
Blob truncated;
441456
blob_zero(&truncated);
442457
blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
443458
blob_append(&truncated, "...", 3);
@@ -1292,13 +1307,17 @@
12921307
url_initialize(&url, "timeline");
12931308
cgi_query_parameters_to_url(&url);
12941309
if( zTagName && g.perm.Read ){
12951310
tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zTagName);
12961311
zThisTag = zTagName;
1312
+ style_submenu_element("Related", "Related", "%s",
1313
+ url_render(&url, "r", zTagName, "t", 0));
12971314
}else if( zBrName && g.perm.Read ){
12981315
tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName);
12991316
zThisTag = zBrName;
1317
+ style_submenu_element("Branch Only", "only", "%s",
1318
+ url_render(&url, "t", zBrName, "r", 0));
13001319
}else{
13011320
tagid = 0;
13021321
}
13031322
if( zMark && zMark[0]==0 ){
13041323
if( zAfter ) zMark = zAfter;
13051324
--- src/timeline.c
+++ src/timeline.c
@@ -230,18 +230,20 @@
230 Stmt fchngQuery; /* Query for file changes on check-ins */
231 static Stmt qbranch;
232 int pendingEndTr = 0; /* True if a </td></tr> is needed */
233 int vid = 0; /* Current checkout version */
234 int dateFormat = 0; /* 0: HH:MM (default) */
 
235 const char *zDateFmt;
236
237 if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){
238 vid = db_lget_int("checkout", 0);
239 }
240 zPrevDate[0] = 0;
241 mxWikiLen = db_get_int("timeline-max-comment", 0);
242 dateFormat = db_get_int("timeline-date-format", 0);
 
243 zDateFmt = P("datefmt");
244 if( zDateFmt ) dateFormat = atoi(zDateFmt);
245 if( tmFlags & TIMELINE_GRAPH ){
246 pGraph = graph_init();
247 }
@@ -434,10 +436,23 @@
434 db_column_blob(pQuery, commentColumn, &comment);
435 if( zType[0]!='c' ){
436 /* Comments for anything other than a check-in are generated by
437 ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */
438 wiki_convert(&comment, 0, WIKI_INLINE);
 
 
 
 
 
 
 
 
 
 
 
 
 
439 }else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
440 Blob truncated;
441 blob_zero(&truncated);
442 blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
443 blob_append(&truncated, "...", 3);
@@ -1292,13 +1307,17 @@
1292 url_initialize(&url, "timeline");
1293 cgi_query_parameters_to_url(&url);
1294 if( zTagName && g.perm.Read ){
1295 tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zTagName);
1296 zThisTag = zTagName;
 
 
1297 }else if( zBrName && g.perm.Read ){
1298 tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName);
1299 zThisTag = zBrName;
 
 
1300 }else{
1301 tagid = 0;
1302 }
1303 if( zMark && zMark[0]==0 ){
1304 if( zAfter ) zMark = zAfter;
1305
--- src/timeline.c
+++ src/timeline.c
@@ -230,18 +230,20 @@
230 Stmt fchngQuery; /* Query for file changes on check-ins */
231 static Stmt qbranch;
232 int pendingEndTr = 0; /* True if a </td></tr> is needed */
233 int vid = 0; /* Current checkout version */
234 int dateFormat = 0; /* 0: HH:MM (default) */
235 int bCommentGitStyle = 0; /* Only show comments through first blank line */
236 const char *zDateFmt;
237
238 if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){
239 vid = db_lget_int("checkout", 0);
240 }
241 zPrevDate[0] = 0;
242 mxWikiLen = db_get_int("timeline-max-comment", 0);
243 dateFormat = db_get_int("timeline-date-format", 0);
244 bCommentGitStyle = db_get_int("timeline-truncate-at-blank", 0);
245 zDateFmt = P("datefmt");
246 if( zDateFmt ) dateFormat = atoi(zDateFmt);
247 if( tmFlags & TIMELINE_GRAPH ){
248 pGraph = graph_init();
249 }
@@ -434,10 +436,23 @@
436 db_column_blob(pQuery, commentColumn, &comment);
437 if( zType[0]!='c' ){
438 /* Comments for anything other than a check-in are generated by
439 ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */
440 wiki_convert(&comment, 0, WIKI_INLINE);
441 }else if( bCommentGitStyle ){
442 /* Truncate comment at first blank line */
443 int ii, jj;
444 int n = blob_size(&comment);
445 char *z = blob_str(&comment);
446 for(ii=0; ii<n; ii++){
447 if( z[ii]=='\n' ){
448 for(jj=ii+1; jj<n && z[jj]!='\n' && fossil_isspace(z[jj]); jj++){}
449 if( z[jj]=='\n' ) break;
450 }
451 }
452 z[ii] = 0;
453 @ <span class="timelineComment">%W(z)</span>
454 }else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
455 Blob truncated;
456 blob_zero(&truncated);
457 blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
458 blob_append(&truncated, "...", 3);
@@ -1292,13 +1307,17 @@
1307 url_initialize(&url, "timeline");
1308 cgi_query_parameters_to_url(&url);
1309 if( zTagName && g.perm.Read ){
1310 tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zTagName);
1311 zThisTag = zTagName;
1312 style_submenu_element("Related", "Related", "%s",
1313 url_render(&url, "r", zTagName, "t", 0));
1314 }else if( zBrName && g.perm.Read ){
1315 tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName);
1316 zThisTag = zBrName;
1317 style_submenu_element("Branch Only", "only", "%s",
1318 url_render(&url, "t", zBrName, "r", 0));
1319 }else{
1320 tagid = 0;
1321 }
1322 if( zMark && zMark[0]==0 ){
1323 if( zAfter ) zMark = zAfter;
1324
+131 -62
--- src/wiki.c
+++ src/wiki.c
@@ -1137,36 +1137,44 @@
11371137
}
11381138
11391139
/*
11401140
** COMMAND: wiki*
11411141
**
1142
-** Usage: %fossil wiki (export|create|commit|list) WikiName
1143
-**
1144
-** Run various subcommands to work with wiki entries.
1145
-**
1146
-** %fossil wiki export PAGENAME ?FILE?
1147
-**
1148
-** Sends the latest version of the PAGENAME wiki
1149
-** entry to the given file or standard output.
1150
-**
1151
-** %fossil wiki commit PAGENAME ?FILE? [-mimetype TEXT-FORMAT]
1152
-**
1153
-** Commit changes to a wiki page from FILE or from standard
1154
-** input. The -mimetype (-M) flag specifies the mime type,
1155
-** defaulting to the type used by the previous version of
1156
-** the page or (for new pages) text/x-fossil-wiki.
1157
-**
1158
-** %fossil wiki create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]
1159
-**
1160
-** Create a new wiki page with initial content taken from
1161
-** FILE or from standard input.
1162
-**
1163
-** %fossil wiki list
1164
-** %fossil wiki ls
1165
-**
1166
-** Lists all wiki entries, one per line, ordered
1167
-** case-insensitively by name.
1142
+** Usage: ../fossil wiki (export|create|commit|list) WikiName
1143
+**
1144
+** Run various subcommands to work with wiki entries or tech notes.
1145
+**
1146
+** ../fossil wiki export ?PAGENAME? ?FILE? [-t|--technote DATETIME ]
1147
+**
1148
+** Sends the latest version of either the PAGENAME wiki entry
1149
+** or the DATETIME tech note to the given file or standard
1150
+** output. One of PAGENAME or DATETIME must be specified.
1151
+**
1152
+** ../fossil wiki (create|commit) PAGENAME ?FILE? ?OPTIONS?
1153
+**
1154
+** Create a new or commit changes to an existing wiki page or
1155
+** technote from FILE or from standard input.
1156
+**
1157
+** Options:
1158
+** -M|--mimetype TEXT-FORMAT The mime type of the update defaulting
1159
+** defaulting to the type used by the
1160
+** previous version of the page or (for
1161
+** new pages) text/x-fossil-wiki.
1162
+** -t|--technote DATETIME Specifies the timestamp of the technote
1163
+** to be created or updated.
1164
+** --technote-tags TAGS The set of tags for a technote.
1165
+** --technote-bgcolor COLOR The color used for the technote on the
1166
+** timeline.
1167
+**
1168
+** ../fossil wiki list ?--technote?
1169
+** ../fossil wiki ls ?--technote?
1170
+**
1171
+** Lists all wiki entries, one per line, ordered
1172
+** case-insensitively by name. The --technote flag
1173
+** specifies that technotes will be listed instead of
1174
+** the wiki entries, which will be listed in order
1175
+** timestamp.
11681176
**
11691177
*/
11701178
void wiki_cmd(void){
11711179
int n;
11721180
db_find_and_open_repository(0, 0);
@@ -1179,33 +1187,54 @@
11791187
}
11801188
11811189
if( strncmp(g.argv[2],"export",n)==0 ){
11821190
const char *zPageName; /* Name of the wiki page to export */
11831191
const char *zFile; /* Name of the output file (0=stdout) */
1192
+ const char *zETime; /* The name of the technote to export */
11841193
int rid; /* Artifact ID of the wiki page */
11851194
int i; /* Loop counter */
11861195
char *zBody = 0; /* Wiki page content */
11871196
Blob body; /* Wiki page content */
11881197
Manifest *pWiki = 0; /* Parsed wiki page content */
1189
- if( (g.argc!=4) && (g.argc!=5) ){
1190
- usage("export PAGENAME ?FILE?");
1191
- }
1192
- zPageName = g.argv[3];
1193
- rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
1194
- " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
1195
- " ORDER BY x.mtime DESC LIMIT 1",
1196
- zPageName
1197
- );
1198
- if( (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
1199
- zBody = pWiki->zWiki;
1200
- }
1201
- if( zBody==0 ){
1202
- fossil_fatal("wiki page [%s] not found",zPageName);
1198
+
1199
+ zETime = find_option("technote","t",1);
1200
+ if( !zETime ){
1201
+ if( (g.argc!=4) && (g.argc!=5) ){
1202
+ usage("export PAGENAME ?FILE?");
1203
+ }
1204
+ zPageName = g.argv[3];
1205
+ rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
1206
+ " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
1207
+ " ORDER BY x.mtime DESC LIMIT 1",
1208
+ zPageName
1209
+ );
1210
+ if( (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
1211
+ zBody = pWiki->zWiki;
1212
+ }
1213
+ if( zBody==0 ){
1214
+ fossil_fatal("wiki page [%s] not found",zPageName);
1215
+ }
1216
+ zFile = (g.argc==4) ? "-" : g.argv[4];
1217
+ }else{
1218
+ if( (g.argc!=3) && (g.argc!=4) ){
1219
+ usage("export ?FILE? --technote DATETIME");
1220
+ }
1221
+ rid = db_int(0, "SELECT objid FROM event"
1222
+ " WHERE datetime(mtime)=datetime('%q') AND type='e'"
1223
+ " ORDER BY mtime DESC LIMIT 1",
1224
+ zETime
1225
+ );
1226
+ if( (pWiki = manifest_get(rid, CFTYPE_EVENT, 0))!=0 ){
1227
+ zBody = pWiki->zWiki;
1228
+ }
1229
+ if( zBody==0 ){
1230
+ fossil_fatal("technote not found");
1231
+ }
1232
+ zFile = (g.argc==3) ? "-" : g.argv[3];
12031233
}
12041234
for(i=strlen(zBody); i>0 && fossil_isspace(zBody[i-1]); i--){}
12051235
zBody[i] = 0;
1206
- zFile = (g.argc==4) ? "-" : g.argv[4];
12071236
blob_init(&body, zBody, -1);
12081237
blob_append(&body, "\n", 1);
12091238
blob_write_to_file(&body, zFile);
12101239
blob_reset(&body);
12111240
manifest_destroy(pWiki);
@@ -1215,37 +1244,70 @@
12151244
const char *zPageName; /* page name */
12161245
Blob content; /* Input content */
12171246
int rid;
12181247
Manifest *pWiki = 0; /* Parsed wiki page content */
12191248
const char *zMimeType = find_option("mimetype", "M", 1);
1249
+ const char *zETime = find_option("technote", "t", 1);
1250
+ const char *zTags = find_option("technote-tags", NULL, 1);
1251
+ const char *zClr = find_option("technote-bgcolor", NULL, 1);
12201252
if( g.argc!=4 && g.argc!=5 ){
1221
- usage("commit|create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]");
1253
+ usage("commit|create PAGENAME ?FILE? [--mimetype TEXT-FORMAT]"
1254
+ " [--technote DATETIME] [--technote-tags TAGS]"
1255
+ " [--technote-bgcolor COLOR]");
12221256
}
12231257
zPageName = g.argv[3];
12241258
if( g.argc==4 ){
12251259
blob_read_from_channel(&content, stdin, -1);
12261260
}else{
12271261
blob_read_from_file(&content, g.argv[4]);
12281262
}
12291263
if(!zMimeType || !*zMimeType){
12301264
/* Try to deduce the mime type based on the prior version. */
1231
- rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
1232
- " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
1233
- " ORDER BY x.mtime DESC LIMIT 1",
1234
- zPageName
1235
- );
1236
- if(rid>0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0
1237
- && (pWiki->zMimetype && *pWiki->zMimetype)){
1238
- zMimeType = pWiki->zMimetype;
1239
- }
1240
- }
1241
- if( g.argv[2][1]=='r' ){
1242
- wiki_cmd_commit(zPageName, 1, &content, zMimeType, 1);
1243
- fossil_print("Created new wiki page %s.\n", zPageName);
1244
- }else{
1245
- wiki_cmd_commit(zPageName, 0, &content, zMimeType, 1);
1246
- fossil_print("Updated wiki page %s.\n", zPageName);
1265
+ if ( !zETime ){
1266
+ rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
1267
+ " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
1268
+ " ORDER BY x.mtime DESC LIMIT 1",
1269
+ zPageName
1270
+ );
1271
+ if(rid>0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0
1272
+ && (pWiki->zMimetype && *pWiki->zMimetype)){
1273
+ zMimeType = pWiki->zMimetype;
1274
+ }
1275
+ }else{
1276
+ rid = db_int(0, "SELECT objid FROM event"
1277
+ " WHERE datetime(mtime)=datetime('%q') AND type='e'"
1278
+ " ORDER BY mtime DESC LIMIT 1",
1279
+ zPageName
1280
+ );
1281
+ if(rid>0 && (pWiki = manifest_get(rid, CFTYPE_EVENT, 0))!=0
1282
+ && (pWiki->zMimetype && *pWiki->zMimetype)){
1283
+ zMimeType = pWiki->zMimetype;
1284
+ }
1285
+ }
1286
+ }
1287
+ if( !zETime ){
1288
+ if( g.argv[2][1]=='r' ){
1289
+ wiki_cmd_commit(zPageName, 1, &content, zMimeType, 1);
1290
+ fossil_print("Created new wiki page %s.\n", zPageName);
1291
+ }else{
1292
+ wiki_cmd_commit(zPageName, 0, &content, zMimeType, 1);
1293
+ fossil_print("Updated wiki page %s.\n", zPageName);
1294
+ }
1295
+ }else{
1296
+ char *zMETime; /* Normalized, mutable version of zETime */
1297
+ zMETime = db_text(0, "SELECT coalesce(datetime(%Q),datetime('now'))",
1298
+ zETime);
1299
+ if( g.argv[2][1]=='r' ){
1300
+ event_cmd_commit(zMETime, 1, &content, zMimeType, zPageName,
1301
+ zTags, zClr);
1302
+ fossil_print("Created new tech note %s.\n", zMETime);
1303
+ }else{
1304
+ event_cmd_commit(zMETime, 0, &content, zMimeType, zPageName,
1305
+ zTags, zClr);
1306
+ fossil_print("Updated tech note %s.\n", zMETime);
1307
+ }
1308
+ free(zMETime);
12471309
}
12481310
manifest_destroy(pWiki);
12491311
blob_reset(&content);
12501312
}else if( strncmp(g.argv[2],"delete",n)==0 ){
12511313
if( g.argc!=5 ){
@@ -1253,14 +1315,21 @@
12531315
}
12541316
fossil_fatal("delete not yet implemented.");
12551317
}else if(( strncmp(g.argv[2],"list",n)==0 )
12561318
|| ( strncmp(g.argv[2],"ls",n)==0 )){
12571319
Stmt q;
1258
- db_prepare(&q,
1259
- "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'"
1260
- " ORDER BY lower(tagname) /*sort*/"
1261
- );
1320
+ if ( !find_option("technote","t",0) ){
1321
+ db_prepare(&q,
1322
+ "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'"
1323
+ " ORDER BY lower(tagname) /*sort*/"
1324
+ );
1325
+ }else{
1326
+ db_prepare(&q,
1327
+ "SELECT datetime(mtime) FROM event WHERE type='e'"
1328
+ " ORDER BY mtime /*sort*/"
1329
+ );
1330
+ }
12621331
while( db_step(&q)==SQLITE_ROW ){
12631332
const char *zName = db_column_text(&q, 0);
12641333
fossil_print( "%s\n",zName);
12651334
}
12661335
db_finalize(&q);
12671336
--- src/wiki.c
+++ src/wiki.c
@@ -1137,36 +1137,44 @@
1137 }
1138
1139 /*
1140 ** COMMAND: wiki*
1141 **
1142 ** Usage: %fossil wiki (export|create|commit|list) WikiName
1143 **
1144 ** Run various subcommands to work with wiki entries.
1145 **
1146 ** %fossil wiki export PAGENAME ?FILE?
1147 **
1148 ** Sends the latest version of the PAGENAME wiki
1149 ** entry to the given file or standard output.
1150 **
1151 ** %fossil wiki commit PAGENAME ?FILE? [-mimetype TEXT-FORMAT]
1152 **
1153 ** Commit changes to a wiki page from FILE or from standard
1154 ** input. The -mimetype (-M) flag specifies the mime type,
1155 ** defaulting to the type used by the previous version of
1156 ** the page or (for new pages) text/x-fossil-wiki.
1157 **
1158 ** %fossil wiki create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]
1159 **
1160 ** Create a new wiki page with initial content taken from
1161 ** FILE or from standard input.
1162 **
1163 ** %fossil wiki list
1164 ** %fossil wiki ls
1165 **
1166 ** Lists all wiki entries, one per line, ordered
1167 ** case-insensitively by name.
 
 
 
 
 
 
 
 
1168 **
1169 */
1170 void wiki_cmd(void){
1171 int n;
1172 db_find_and_open_repository(0, 0);
@@ -1179,33 +1187,54 @@
1179 }
1180
1181 if( strncmp(g.argv[2],"export",n)==0 ){
1182 const char *zPageName; /* Name of the wiki page to export */
1183 const char *zFile; /* Name of the output file (0=stdout) */
 
1184 int rid; /* Artifact ID of the wiki page */
1185 int i; /* Loop counter */
1186 char *zBody = 0; /* Wiki page content */
1187 Blob body; /* Wiki page content */
1188 Manifest *pWiki = 0; /* Parsed wiki page content */
1189 if( (g.argc!=4) && (g.argc!=5) ){
1190 usage("export PAGENAME ?FILE?");
1191 }
1192 zPageName = g.argv[3];
1193 rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
1194 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
1195 " ORDER BY x.mtime DESC LIMIT 1",
1196 zPageName
1197 );
1198 if( (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
1199 zBody = pWiki->zWiki;
1200 }
1201 if( zBody==0 ){
1202 fossil_fatal("wiki page [%s] not found",zPageName);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1203 }
1204 for(i=strlen(zBody); i>0 && fossil_isspace(zBody[i-1]); i--){}
1205 zBody[i] = 0;
1206 zFile = (g.argc==4) ? "-" : g.argv[4];
1207 blob_init(&body, zBody, -1);
1208 blob_append(&body, "\n", 1);
1209 blob_write_to_file(&body, zFile);
1210 blob_reset(&body);
1211 manifest_destroy(pWiki);
@@ -1215,37 +1244,70 @@
1215 const char *zPageName; /* page name */
1216 Blob content; /* Input content */
1217 int rid;
1218 Manifest *pWiki = 0; /* Parsed wiki page content */
1219 const char *zMimeType = find_option("mimetype", "M", 1);
 
 
 
1220 if( g.argc!=4 && g.argc!=5 ){
1221 usage("commit|create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]");
 
 
1222 }
1223 zPageName = g.argv[3];
1224 if( g.argc==4 ){
1225 blob_read_from_channel(&content, stdin, -1);
1226 }else{
1227 blob_read_from_file(&content, g.argv[4]);
1228 }
1229 if(!zMimeType || !*zMimeType){
1230 /* Try to deduce the mime type based on the prior version. */
1231 rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
1232 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
1233 " ORDER BY x.mtime DESC LIMIT 1",
1234 zPageName
1235 );
1236 if(rid>0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0
1237 && (pWiki->zMimetype && *pWiki->zMimetype)){
1238 zMimeType = pWiki->zMimetype;
1239 }
1240 }
1241 if( g.argv[2][1]=='r' ){
1242 wiki_cmd_commit(zPageName, 1, &content, zMimeType, 1);
1243 fossil_print("Created new wiki page %s.\n", zPageName);
1244 }else{
1245 wiki_cmd_commit(zPageName, 0, &content, zMimeType, 1);
1246 fossil_print("Updated wiki page %s.\n", zPageName);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1247 }
1248 manifest_destroy(pWiki);
1249 blob_reset(&content);
1250 }else if( strncmp(g.argv[2],"delete",n)==0 ){
1251 if( g.argc!=5 ){
@@ -1253,14 +1315,21 @@
1253 }
1254 fossil_fatal("delete not yet implemented.");
1255 }else if(( strncmp(g.argv[2],"list",n)==0 )
1256 || ( strncmp(g.argv[2],"ls",n)==0 )){
1257 Stmt q;
1258 db_prepare(&q,
1259 "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'"
1260 " ORDER BY lower(tagname) /*sort*/"
1261 );
 
 
 
 
 
 
 
1262 while( db_step(&q)==SQLITE_ROW ){
1263 const char *zName = db_column_text(&q, 0);
1264 fossil_print( "%s\n",zName);
1265 }
1266 db_finalize(&q);
1267
--- src/wiki.c
+++ src/wiki.c
@@ -1137,36 +1137,44 @@
1137 }
1138
1139 /*
1140 ** COMMAND: wiki*
1141 **
1142 ** Usage: ../fossil wiki (export|create|commit|list) WikiName
1143 **
1144 ** Run various subcommands to work with wiki entries or tech notes.
1145 **
1146 ** ../fossil wiki export ?PAGENAME? ?FILE? [-t|--technote DATETIME ]
1147 **
1148 ** Sends the latest version of either the PAGENAME wiki entry
1149 ** or the DATETIME tech note to the given file or standard
1150 ** output. One of PAGENAME or DATETIME must be specified.
1151 **
1152 ** ../fossil wiki (create|commit) PAGENAME ?FILE? ?OPTIONS?
1153 **
1154 ** Create a new or commit changes to an existing wiki page or
1155 ** technote from FILE or from standard input.
1156 **
1157 ** Options:
1158 ** -M|--mimetype TEXT-FORMAT The mime type of the update defaulting
1159 ** defaulting to the type used by the
1160 ** previous version of the page or (for
1161 ** new pages) text/x-fossil-wiki.
1162 ** -t|--technote DATETIME Specifies the timestamp of the technote
1163 ** to be created or updated.
1164 ** --technote-tags TAGS The set of tags for a technote.
1165 ** --technote-bgcolor COLOR The color used for the technote on the
1166 ** timeline.
1167 **
1168 ** ../fossil wiki list ?--technote?
1169 ** ../fossil wiki ls ?--technote?
1170 **
1171 ** Lists all wiki entries, one per line, ordered
1172 ** case-insensitively by name. The --technote flag
1173 ** specifies that technotes will be listed instead of
1174 ** the wiki entries, which will be listed in order
1175 ** timestamp.
1176 **
1177 */
1178 void wiki_cmd(void){
1179 int n;
1180 db_find_and_open_repository(0, 0);
@@ -1179,33 +1187,54 @@
1187 }
1188
1189 if( strncmp(g.argv[2],"export",n)==0 ){
1190 const char *zPageName; /* Name of the wiki page to export */
1191 const char *zFile; /* Name of the output file (0=stdout) */
1192 const char *zETime; /* The name of the technote to export */
1193 int rid; /* Artifact ID of the wiki page */
1194 int i; /* Loop counter */
1195 char *zBody = 0; /* Wiki page content */
1196 Blob body; /* Wiki page content */
1197 Manifest *pWiki = 0; /* Parsed wiki page content */
1198
1199 zETime = find_option("technote","t",1);
1200 if( !zETime ){
1201 if( (g.argc!=4) && (g.argc!=5) ){
1202 usage("export PAGENAME ?FILE?");
1203 }
1204 zPageName = g.argv[3];
1205 rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
1206 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
1207 " ORDER BY x.mtime DESC LIMIT 1",
1208 zPageName
1209 );
1210 if( (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
1211 zBody = pWiki->zWiki;
1212 }
1213 if( zBody==0 ){
1214 fossil_fatal("wiki page [%s] not found",zPageName);
1215 }
1216 zFile = (g.argc==4) ? "-" : g.argv[4];
1217 }else{
1218 if( (g.argc!=3) && (g.argc!=4) ){
1219 usage("export ?FILE? --technote DATETIME");
1220 }
1221 rid = db_int(0, "SELECT objid FROM event"
1222 " WHERE datetime(mtime)=datetime('%q') AND type='e'"
1223 " ORDER BY mtime DESC LIMIT 1",
1224 zETime
1225 );
1226 if( (pWiki = manifest_get(rid, CFTYPE_EVENT, 0))!=0 ){
1227 zBody = pWiki->zWiki;
1228 }
1229 if( zBody==0 ){
1230 fossil_fatal("technote not found");
1231 }
1232 zFile = (g.argc==3) ? "-" : g.argv[3];
1233 }
1234 for(i=strlen(zBody); i>0 && fossil_isspace(zBody[i-1]); i--){}
1235 zBody[i] = 0;
 
1236 blob_init(&body, zBody, -1);
1237 blob_append(&body, "\n", 1);
1238 blob_write_to_file(&body, zFile);
1239 blob_reset(&body);
1240 manifest_destroy(pWiki);
@@ -1215,37 +1244,70 @@
1244 const char *zPageName; /* page name */
1245 Blob content; /* Input content */
1246 int rid;
1247 Manifest *pWiki = 0; /* Parsed wiki page content */
1248 const char *zMimeType = find_option("mimetype", "M", 1);
1249 const char *zETime = find_option("technote", "t", 1);
1250 const char *zTags = find_option("technote-tags", NULL, 1);
1251 const char *zClr = find_option("technote-bgcolor", NULL, 1);
1252 if( g.argc!=4 && g.argc!=5 ){
1253 usage("commit|create PAGENAME ?FILE? [--mimetype TEXT-FORMAT]"
1254 " [--technote DATETIME] [--technote-tags TAGS]"
1255 " [--technote-bgcolor COLOR]");
1256 }
1257 zPageName = g.argv[3];
1258 if( g.argc==4 ){
1259 blob_read_from_channel(&content, stdin, -1);
1260 }else{
1261 blob_read_from_file(&content, g.argv[4]);
1262 }
1263 if(!zMimeType || !*zMimeType){
1264 /* Try to deduce the mime type based on the prior version. */
1265 if ( !zETime ){
1266 rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
1267 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
1268 " ORDER BY x.mtime DESC LIMIT 1",
1269 zPageName
1270 );
1271 if(rid>0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0
1272 && (pWiki->zMimetype && *pWiki->zMimetype)){
1273 zMimeType = pWiki->zMimetype;
1274 }
1275 }else{
1276 rid = db_int(0, "SELECT objid FROM event"
1277 " WHERE datetime(mtime)=datetime('%q') AND type='e'"
1278 " ORDER BY mtime DESC LIMIT 1",
1279 zPageName
1280 );
1281 if(rid>0 && (pWiki = manifest_get(rid, CFTYPE_EVENT, 0))!=0
1282 && (pWiki->zMimetype && *pWiki->zMimetype)){
1283 zMimeType = pWiki->zMimetype;
1284 }
1285 }
1286 }
1287 if( !zETime ){
1288 if( g.argv[2][1]=='r' ){
1289 wiki_cmd_commit(zPageName, 1, &content, zMimeType, 1);
1290 fossil_print("Created new wiki page %s.\n", zPageName);
1291 }else{
1292 wiki_cmd_commit(zPageName, 0, &content, zMimeType, 1);
1293 fossil_print("Updated wiki page %s.\n", zPageName);
1294 }
1295 }else{
1296 char *zMETime; /* Normalized, mutable version of zETime */
1297 zMETime = db_text(0, "SELECT coalesce(datetime(%Q),datetime('now'))",
1298 zETime);
1299 if( g.argv[2][1]=='r' ){
1300 event_cmd_commit(zMETime, 1, &content, zMimeType, zPageName,
1301 zTags, zClr);
1302 fossil_print("Created new tech note %s.\n", zMETime);
1303 }else{
1304 event_cmd_commit(zMETime, 0, &content, zMimeType, zPageName,
1305 zTags, zClr);
1306 fossil_print("Updated tech note %s.\n", zMETime);
1307 }
1308 free(zMETime);
1309 }
1310 manifest_destroy(pWiki);
1311 blob_reset(&content);
1312 }else if( strncmp(g.argv[2],"delete",n)==0 ){
1313 if( g.argc!=5 ){
@@ -1253,14 +1315,21 @@
1315 }
1316 fossil_fatal("delete not yet implemented.");
1317 }else if(( strncmp(g.argv[2],"list",n)==0 )
1318 || ( strncmp(g.argv[2],"ls",n)==0 )){
1319 Stmt q;
1320 if ( !find_option("technote","t",0) ){
1321 db_prepare(&q,
1322 "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'"
1323 " ORDER BY lower(tagname) /*sort*/"
1324 );
1325 }else{
1326 db_prepare(&q,
1327 "SELECT datetime(mtime) FROM event WHERE type='e'"
1328 " ORDER BY mtime /*sort*/"
1329 );
1330 }
1331 while( db_step(&q)==SQLITE_ROW ){
1332 const char *zName = db_column_text(&q, 0);
1333 fossil_print( "%s\n",zName);
1334 }
1335 db_finalize(&q);
1336
+2 -2
--- src/zip.c
+++ src/zip.c
@@ -142,18 +142,18 @@
142142
char zOutBuf[100000];
143143
144144
/* Fill in as much of the header as we know.
145145
*/
146146
nBlob = pFile ? blob_size(pFile) : 0;
147
- if( nBlob>0 ){
147
+ if( pFile ){ /* This is a file, possibly empty... */
148148
iMethod = 8;
149149
switch( mPerm ){
150150
case PERM_LNK: iMode = 0120755; break;
151151
case PERM_EXE: iMode = 0100755; break;
152152
default: iMode = 0100644; break;
153153
}
154
- }else{
154
+ }else{ /* This is a directory, no blob... */
155155
iMethod = 0;
156156
iMode = 040755;
157157
}
158158
nameLen = strlen(zName);
159159
memset(zHdr, 0, sizeof(zHdr));
160160
--- src/zip.c
+++ src/zip.c
@@ -142,18 +142,18 @@
142 char zOutBuf[100000];
143
144 /* Fill in as much of the header as we know.
145 */
146 nBlob = pFile ? blob_size(pFile) : 0;
147 if( nBlob>0 ){
148 iMethod = 8;
149 switch( mPerm ){
150 case PERM_LNK: iMode = 0120755; break;
151 case PERM_EXE: iMode = 0100755; break;
152 default: iMode = 0100644; break;
153 }
154 }else{
155 iMethod = 0;
156 iMode = 040755;
157 }
158 nameLen = strlen(zName);
159 memset(zHdr, 0, sizeof(zHdr));
160
--- src/zip.c
+++ src/zip.c
@@ -142,18 +142,18 @@
142 char zOutBuf[100000];
143
144 /* Fill in as much of the header as we know.
145 */
146 nBlob = pFile ? blob_size(pFile) : 0;
147 if( pFile ){ /* This is a file, possibly empty... */
148 iMethod = 8;
149 switch( mPerm ){
150 case PERM_LNK: iMode = 0120755; break;
151 case PERM_EXE: iMode = 0100755; break;
152 default: iMode = 0100644; break;
153 }
154 }else{ /* This is a directory, no blob... */
155 iMethod = 0;
156 iMode = 040755;
157 }
158 nameLen = strlen(zName);
159 memset(zHdr, 0, sizeof(zHdr));
160
+3 -3
--- test/clean.test
+++ test/clean.test
@@ -57,11 +57,11 @@
5757
test clean-5 {[normalize_result] eq {}}
5858
5959
###############################################################################
6060
6161
fossil undo
62
-test clean-6 {[normalize_result] eq {NEW f2}}
62
+test clean-6 {[normalize_result] eq {NEW f2}}
6363
test clean-7 {[read_file f2] eq "f2 line"}
6464
6565
###############################################################################
6666
6767
fossil extra
@@ -87,11 +87,11 @@
8787
test clean-11 {[normalize_result] eq {f3}}
8888
8989
###############################################################################
9090
9191
fossil undo
92
-test clean-12 {[normalize_result] eq {NEW f2}}
92
+test clean-12 {[normalize_result] eq {NEW f2}}
9393
test clean-13 {[read_file f2] eq "f2 line"}
9494
test clean-14 {[read_file f3] eq [string repeat ABCDEFGHIJK 1048576]}
9595
9696
###############################################################################
9797
@@ -112,11 +112,11 @@
112112
test clean-17 {[normalize_result] eq {}}
113113
114114
###############################################################################
115115
116116
fossil undo
117
-test clean-18 {[normalize_result] eq {NEW f2}}
117
+test clean-18 {[normalize_result] eq {NEW f2}}
118118
test clean-19 {[read_file f2] eq "f2 line"}
119119
120120
###############################################################################
121121
122122
write_file f4 [string repeat KJIHGFEDCBA 1048576]
123123
--- test/clean.test
+++ test/clean.test
@@ -57,11 +57,11 @@
57 test clean-5 {[normalize_result] eq {}}
58
59 ###############################################################################
60
61 fossil undo
62 test clean-6 {[normalize_result] eq {NEW f2}}
63 test clean-7 {[read_file f2] eq "f2 line"}
64
65 ###############################################################################
66
67 fossil extra
@@ -87,11 +87,11 @@
87 test clean-11 {[normalize_result] eq {f3}}
88
89 ###############################################################################
90
91 fossil undo
92 test clean-12 {[normalize_result] eq {NEW f2}}
93 test clean-13 {[read_file f2] eq "f2 line"}
94 test clean-14 {[read_file f3] eq [string repeat ABCDEFGHIJK 1048576]}
95
96 ###############################################################################
97
@@ -112,11 +112,11 @@
112 test clean-17 {[normalize_result] eq {}}
113
114 ###############################################################################
115
116 fossil undo
117 test clean-18 {[normalize_result] eq {NEW f2}}
118 test clean-19 {[read_file f2] eq "f2 line"}
119
120 ###############################################################################
121
122 write_file f4 [string repeat KJIHGFEDCBA 1048576]
123
--- test/clean.test
+++ test/clean.test
@@ -57,11 +57,11 @@
57 test clean-5 {[normalize_result] eq {}}
58
59 ###############################################################################
60
61 fossil undo
62 test clean-6 {[normalize_result] eq {NEW f2}}
63 test clean-7 {[read_file f2] eq "f2 line"}
64
65 ###############################################################################
66
67 fossil extra
@@ -87,11 +87,11 @@
87 test clean-11 {[normalize_result] eq {f3}}
88
89 ###############################################################################
90
91 fossil undo
92 test clean-12 {[normalize_result] eq {NEW f2}}
93 test clean-13 {[read_file f2] eq "f2 line"}
94 test clean-14 {[read_file f3] eq [string repeat ABCDEFGHIJK 1048576]}
95
96 ###############################################################################
97
@@ -112,11 +112,11 @@
112 test clean-17 {[normalize_result] eq {}}
113
114 ###############################################################################
115
116 fossil undo
117 test clean-18 {[normalize_result] eq {NEW f2}}
118 test clean-19 {[read_file f2] eq "f2 line"}
119
120 ###############################################################################
121
122 write_file f4 [string repeat KJIHGFEDCBA 1048576]
123
+16 -16
--- test/mv-rm.test
+++ test/mv-rm.test
@@ -68,11 +68,11 @@
6868
fossil mv ../f1 .
6969
test mv-soft-relative-1 {$RESULT eq "RENAME f1 subdir1/f1"}
7070
7171
fossil revert
7272
test mv-soft-relative-2 {
73
- [normalize_result] eq "DELETE: subdir1/f1\nREVERTED: f1${undoMsg}"
73
+ [normalize_result] eq "DELETE subdir1/f1\nREVERT f1${undoMsg}"
7474
}
7575
7676
cd $rootDir
7777
7878
###################################
@@ -85,11 +85,11 @@
8585
fossil mv ../f2 ./f2
8686
test mv-soft-relative-3 {$RESULT eq "RENAME f2 subdir2/f2"}
8787
8888
fossil revert
8989
test mv-soft-relative-4 {
90
- [normalize_result] eq "DELETE: subdir2/f2\nREVERTED: f2${undoMsg}"
90
+ [normalize_result] eq "DELETE subdir2/f2\nREVERT f2${undoMsg}"
9191
}
9292
9393
cd $rootDir
9494
9595
########################################
@@ -104,11 +104,11 @@
104104
[normalize_result] eq "RENAME f3 subdir3/f3\nMOVED_FILE ${rootDir}/f3"
105105
}
106106
107107
fossil revert
108108
test mv-hard-relative-2 {
109
- [normalize_result] eq "DELETE: subdir3/f3\nREVERTED: f3${undoMsg}"
109
+ [normalize_result] eq "DELETE subdir3/f3\nREVERT f3${undoMsg}"
110110
}
111111
112112
cd $rootDir
113113
114114
###################################
@@ -123,11 +123,11 @@
123123
[normalize_result] eq "RENAME f4 subdir4/f4\nMOVED_FILE ${rootDir}/f4"
124124
}
125125
126126
fossil revert
127127
test mv-hard-relative-4 {
128
- [normalize_result] eq "DELETE: subdir4/f4\nREVERTED: f4${undoMsg}"
128
+ [normalize_result] eq "DELETE subdir4/f4\nREVERT f4${undoMsg}"
129129
}
130130
131131
cd $rootDir
132132
133133
########################################
@@ -140,11 +140,11 @@
140140
fossil mv [file join $rootDir f5] [file join $rootDir subdir5]
141141
test mv-soft-absolute-1 {$RESULT eq "RENAME f5 subdir5/f5"}
142142
143143
fossil revert
144144
test mv-soft-absolute-2 {
145
- [normalize_result] eq "DELETE: subdir5/f5\nREVERTED: f5${undoMsg}"
145
+ [normalize_result] eq "DELETE subdir5/f5\nREVERT f5${undoMsg}"
146146
}
147147
148148
cd $rootDir
149149
150150
###################################
@@ -157,11 +157,11 @@
157157
fossil mv [file join $rootDir f6] [file join $rootDir subdir6 f6]
158158
test mv-soft-absolute-3 {$RESULT eq "RENAME f6 subdir6/f6"}
159159
160160
fossil revert
161161
test mv-soft-absolute-4 {
162
- [normalize_result] eq "DELETE: subdir6/f6\nREVERTED: f6${undoMsg}"
162
+ [normalize_result] eq "DELETE subdir6/f6\nREVERT f6${undoMsg}"
163163
}
164164
165165
cd $rootDir
166166
167167
########################################
@@ -176,11 +176,11 @@
176176
[normalize_result] eq "RENAME f7 subdir7/f7\nMOVED_FILE ${rootDir}/f7"
177177
}
178178
179179
fossil revert
180180
test mv-hard-absolute-2 {
181
- [normalize_result] eq "DELETE: subdir7/f7\nREVERTED: f7${undoMsg}"
181
+ [normalize_result] eq "DELETE subdir7/f7\nREVERT f7${undoMsg}"
182182
}
183183
184184
cd $rootDir
185185
186186
###################################
@@ -195,11 +195,11 @@
195195
[normalize_result] eq "RENAME f8 subdir8/f8\nMOVED_FILE ${rootDir}/f8"
196196
}
197197
198198
fossil revert
199199
test mv-hard-absolute-4 {
200
- [normalize_result] eq "DELETE: subdir8/f8\nREVERTED: f8${undoMsg}"
200
+ [normalize_result] eq "DELETE subdir8/f8\nREVERT f8${undoMsg}"
201201
}
202202
203203
cd $rootDir
204204
205205
##########################################
@@ -221,11 +221,11 @@
221221
}
222222
223223
fossil revert
224224
test rm-soft-relative-4 {
225225
[normalize_result] eq \
226
- "REVERTED: subdirB/f9\nREVERTED: subdirC/f10\nREVERTED: subdirC/f11${undoMsg}"
226
+ "REVERT subdirB/f9\nREVERT subdirC/f10\nREVERT subdirC/f11${undoMsg}"
227227
}
228228
229229
cd $rootDir
230230
231231
######################################
@@ -238,11 +238,11 @@
238238
fossil rm ../f2
239239
test rm-soft-relative-5 {$RESULT eq "DELETED f2"}
240240
241241
fossil revert
242242
test rm-soft-relative-6 {
243
- [normalize_result] eq "REVERTED: f2${undoMsg}"
243
+ [normalize_result] eq "REVERT f2${undoMsg}"
244244
}
245245
246246
cd $rootDir
247247
248248
###########################################
@@ -271,11 +271,11 @@
271271
}
272272
273273
fossil revert
274274
test rm-hard-relative-4 {
275275
[normalize_result] eq \
276
- "REVERTED: subdirB/f9\nREVERTED: subdirC/f10\nREVERTED: subdirC/f11${undoMsg}"
276
+ "REVERT subdirB/f9\nREVERT subdirC/f10\nREVERT subdirC/f11${undoMsg}"
277277
}
278278
279279
cd $rootDir
280280
281281
######################################
@@ -290,11 +290,11 @@
290290
[normalize_result] eq "DELETED f4\nDELETED_FILE ${rootDir}/f4"
291291
}
292292
293293
fossil revert
294294
test rm-hard-relative-6 {
295
- [normalize_result] eq "REVERTED: f4${undoMsg}"
295
+ [normalize_result] eq "REVERT f4${undoMsg}"
296296
}
297297
298298
cd $rootDir
299299
300300
###########################################
@@ -316,11 +316,11 @@
316316
}
317317
318318
fossil revert
319319
test rm-soft-absolute-4 {
320320
[normalize_result] eq \
321
- "REVERTED: subdirB/f9\nREVERTED: subdirC/f10\nREVERTED: subdirC/f11${undoMsg}"
321
+ "REVERT subdirB/f9\nREVERT subdirC/f10\nREVERT subdirC/f11${undoMsg}"
322322
}
323323
324324
cd $rootDir
325325
326326
######################################
@@ -333,11 +333,11 @@
333333
fossil rm [file join $rootDir f6]
334334
test rm-soft-absolute-5 {$RESULT eq "DELETED f6"}
335335
336336
fossil revert
337337
test rm-soft-absolute-6 {
338
- [normalize_result] eq "REVERTED: f6${undoMsg}"
338
+ [normalize_result] eq "REVERT f6${undoMsg}"
339339
}
340340
341341
cd $rootDir
342342
343343
###########################################
@@ -364,11 +364,11 @@
364364
}
365365
366366
fossil revert
367367
test rm-hard-absolute-4 {
368368
[normalize_result] eq \
369
- "REVERTED: subdirB/f9\nREVERTED: subdirC/f10\nREVERTED: subdirC/f11${undoMsg}"
369
+ "REVERT subdirB/f9\nREVERT subdirC/f10\nREVERT subdirC/f11${undoMsg}"
370370
}
371371
372372
cd $rootDir
373373
374374
######################################
@@ -383,9 +383,9 @@
383383
[normalize_result] eq "DELETED f8\nDELETED_FILE ${rootDir}/f8"
384384
}
385385
386386
fossil revert
387387
test rm-hard-absolute-6 {
388
- [normalize_result] eq "REVERTED: f8${undoMsg}"
388
+ [normalize_result] eq "REVERT f8${undoMsg}"
389389
}
390390
391391
cd $rootDir
392392
--- test/mv-rm.test
+++ test/mv-rm.test
@@ -68,11 +68,11 @@
68 fossil mv ../f1 .
69 test mv-soft-relative-1 {$RESULT eq "RENAME f1 subdir1/f1"}
70
71 fossil revert
72 test mv-soft-relative-2 {
73 [normalize_result] eq "DELETE: subdir1/f1\nREVERTED: f1${undoMsg}"
74 }
75
76 cd $rootDir
77
78 ###################################
@@ -85,11 +85,11 @@
85 fossil mv ../f2 ./f2
86 test mv-soft-relative-3 {$RESULT eq "RENAME f2 subdir2/f2"}
87
88 fossil revert
89 test mv-soft-relative-4 {
90 [normalize_result] eq "DELETE: subdir2/f2\nREVERTED: f2${undoMsg}"
91 }
92
93 cd $rootDir
94
95 ########################################
@@ -104,11 +104,11 @@
104 [normalize_result] eq "RENAME f3 subdir3/f3\nMOVED_FILE ${rootDir}/f3"
105 }
106
107 fossil revert
108 test mv-hard-relative-2 {
109 [normalize_result] eq "DELETE: subdir3/f3\nREVERTED: f3${undoMsg}"
110 }
111
112 cd $rootDir
113
114 ###################################
@@ -123,11 +123,11 @@
123 [normalize_result] eq "RENAME f4 subdir4/f4\nMOVED_FILE ${rootDir}/f4"
124 }
125
126 fossil revert
127 test mv-hard-relative-4 {
128 [normalize_result] eq "DELETE: subdir4/f4\nREVERTED: f4${undoMsg}"
129 }
130
131 cd $rootDir
132
133 ########################################
@@ -140,11 +140,11 @@
140 fossil mv [file join $rootDir f5] [file join $rootDir subdir5]
141 test mv-soft-absolute-1 {$RESULT eq "RENAME f5 subdir5/f5"}
142
143 fossil revert
144 test mv-soft-absolute-2 {
145 [normalize_result] eq "DELETE: subdir5/f5\nREVERTED: f5${undoMsg}"
146 }
147
148 cd $rootDir
149
150 ###################################
@@ -157,11 +157,11 @@
157 fossil mv [file join $rootDir f6] [file join $rootDir subdir6 f6]
158 test mv-soft-absolute-3 {$RESULT eq "RENAME f6 subdir6/f6"}
159
160 fossil revert
161 test mv-soft-absolute-4 {
162 [normalize_result] eq "DELETE: subdir6/f6\nREVERTED: f6${undoMsg}"
163 }
164
165 cd $rootDir
166
167 ########################################
@@ -176,11 +176,11 @@
176 [normalize_result] eq "RENAME f7 subdir7/f7\nMOVED_FILE ${rootDir}/f7"
177 }
178
179 fossil revert
180 test mv-hard-absolute-2 {
181 [normalize_result] eq "DELETE: subdir7/f7\nREVERTED: f7${undoMsg}"
182 }
183
184 cd $rootDir
185
186 ###################################
@@ -195,11 +195,11 @@
195 [normalize_result] eq "RENAME f8 subdir8/f8\nMOVED_FILE ${rootDir}/f8"
196 }
197
198 fossil revert
199 test mv-hard-absolute-4 {
200 [normalize_result] eq "DELETE: subdir8/f8\nREVERTED: f8${undoMsg}"
201 }
202
203 cd $rootDir
204
205 ##########################################
@@ -221,11 +221,11 @@
221 }
222
223 fossil revert
224 test rm-soft-relative-4 {
225 [normalize_result] eq \
226 "REVERTED: subdirB/f9\nREVERTED: subdirC/f10\nREVERTED: subdirC/f11${undoMsg}"
227 }
228
229 cd $rootDir
230
231 ######################################
@@ -238,11 +238,11 @@
238 fossil rm ../f2
239 test rm-soft-relative-5 {$RESULT eq "DELETED f2"}
240
241 fossil revert
242 test rm-soft-relative-6 {
243 [normalize_result] eq "REVERTED: f2${undoMsg}"
244 }
245
246 cd $rootDir
247
248 ###########################################
@@ -271,11 +271,11 @@
271 }
272
273 fossil revert
274 test rm-hard-relative-4 {
275 [normalize_result] eq \
276 "REVERTED: subdirB/f9\nREVERTED: subdirC/f10\nREVERTED: subdirC/f11${undoMsg}"
277 }
278
279 cd $rootDir
280
281 ######################################
@@ -290,11 +290,11 @@
290 [normalize_result] eq "DELETED f4\nDELETED_FILE ${rootDir}/f4"
291 }
292
293 fossil revert
294 test rm-hard-relative-6 {
295 [normalize_result] eq "REVERTED: f4${undoMsg}"
296 }
297
298 cd $rootDir
299
300 ###########################################
@@ -316,11 +316,11 @@
316 }
317
318 fossil revert
319 test rm-soft-absolute-4 {
320 [normalize_result] eq \
321 "REVERTED: subdirB/f9\nREVERTED: subdirC/f10\nREVERTED: subdirC/f11${undoMsg}"
322 }
323
324 cd $rootDir
325
326 ######################################
@@ -333,11 +333,11 @@
333 fossil rm [file join $rootDir f6]
334 test rm-soft-absolute-5 {$RESULT eq "DELETED f6"}
335
336 fossil revert
337 test rm-soft-absolute-6 {
338 [normalize_result] eq "REVERTED: f6${undoMsg}"
339 }
340
341 cd $rootDir
342
343 ###########################################
@@ -364,11 +364,11 @@
364 }
365
366 fossil revert
367 test rm-hard-absolute-4 {
368 [normalize_result] eq \
369 "REVERTED: subdirB/f9\nREVERTED: subdirC/f10\nREVERTED: subdirC/f11${undoMsg}"
370 }
371
372 cd $rootDir
373
374 ######################################
@@ -383,9 +383,9 @@
383 [normalize_result] eq "DELETED f8\nDELETED_FILE ${rootDir}/f8"
384 }
385
386 fossil revert
387 test rm-hard-absolute-6 {
388 [normalize_result] eq "REVERTED: f8${undoMsg}"
389 }
390
391 cd $rootDir
392
--- test/mv-rm.test
+++ test/mv-rm.test
@@ -68,11 +68,11 @@
68 fossil mv ../f1 .
69 test mv-soft-relative-1 {$RESULT eq "RENAME f1 subdir1/f1"}
70
71 fossil revert
72 test mv-soft-relative-2 {
73 [normalize_result] eq "DELETE subdir1/f1\nREVERT f1${undoMsg}"
74 }
75
76 cd $rootDir
77
78 ###################################
@@ -85,11 +85,11 @@
85 fossil mv ../f2 ./f2
86 test mv-soft-relative-3 {$RESULT eq "RENAME f2 subdir2/f2"}
87
88 fossil revert
89 test mv-soft-relative-4 {
90 [normalize_result] eq "DELETE subdir2/f2\nREVERT f2${undoMsg}"
91 }
92
93 cd $rootDir
94
95 ########################################
@@ -104,11 +104,11 @@
104 [normalize_result] eq "RENAME f3 subdir3/f3\nMOVED_FILE ${rootDir}/f3"
105 }
106
107 fossil revert
108 test mv-hard-relative-2 {
109 [normalize_result] eq "DELETE subdir3/f3\nREVERT f3${undoMsg}"
110 }
111
112 cd $rootDir
113
114 ###################################
@@ -123,11 +123,11 @@
123 [normalize_result] eq "RENAME f4 subdir4/f4\nMOVED_FILE ${rootDir}/f4"
124 }
125
126 fossil revert
127 test mv-hard-relative-4 {
128 [normalize_result] eq "DELETE subdir4/f4\nREVERT f4${undoMsg}"
129 }
130
131 cd $rootDir
132
133 ########################################
@@ -140,11 +140,11 @@
140 fossil mv [file join $rootDir f5] [file join $rootDir subdir5]
141 test mv-soft-absolute-1 {$RESULT eq "RENAME f5 subdir5/f5"}
142
143 fossil revert
144 test mv-soft-absolute-2 {
145 [normalize_result] eq "DELETE subdir5/f5\nREVERT f5${undoMsg}"
146 }
147
148 cd $rootDir
149
150 ###################################
@@ -157,11 +157,11 @@
157 fossil mv [file join $rootDir f6] [file join $rootDir subdir6 f6]
158 test mv-soft-absolute-3 {$RESULT eq "RENAME f6 subdir6/f6"}
159
160 fossil revert
161 test mv-soft-absolute-4 {
162 [normalize_result] eq "DELETE subdir6/f6\nREVERT f6${undoMsg}"
163 }
164
165 cd $rootDir
166
167 ########################################
@@ -176,11 +176,11 @@
176 [normalize_result] eq "RENAME f7 subdir7/f7\nMOVED_FILE ${rootDir}/f7"
177 }
178
179 fossil revert
180 test mv-hard-absolute-2 {
181 [normalize_result] eq "DELETE subdir7/f7\nREVERT f7${undoMsg}"
182 }
183
184 cd $rootDir
185
186 ###################################
@@ -195,11 +195,11 @@
195 [normalize_result] eq "RENAME f8 subdir8/f8\nMOVED_FILE ${rootDir}/f8"
196 }
197
198 fossil revert
199 test mv-hard-absolute-4 {
200 [normalize_result] eq "DELETE subdir8/f8\nREVERT f8${undoMsg}"
201 }
202
203 cd $rootDir
204
205 ##########################################
@@ -221,11 +221,11 @@
221 }
222
223 fossil revert
224 test rm-soft-relative-4 {
225 [normalize_result] eq \
226 "REVERT subdirB/f9\nREVERT subdirC/f10\nREVERT subdirC/f11${undoMsg}"
227 }
228
229 cd $rootDir
230
231 ######################################
@@ -238,11 +238,11 @@
238 fossil rm ../f2
239 test rm-soft-relative-5 {$RESULT eq "DELETED f2"}
240
241 fossil revert
242 test rm-soft-relative-6 {
243 [normalize_result] eq "REVERT f2${undoMsg}"
244 }
245
246 cd $rootDir
247
248 ###########################################
@@ -271,11 +271,11 @@
271 }
272
273 fossil revert
274 test rm-hard-relative-4 {
275 [normalize_result] eq \
276 "REVERT subdirB/f9\nREVERT subdirC/f10\nREVERT subdirC/f11${undoMsg}"
277 }
278
279 cd $rootDir
280
281 ######################################
@@ -290,11 +290,11 @@
290 [normalize_result] eq "DELETED f4\nDELETED_FILE ${rootDir}/f4"
291 }
292
293 fossil revert
294 test rm-hard-relative-6 {
295 [normalize_result] eq "REVERT f4${undoMsg}"
296 }
297
298 cd $rootDir
299
300 ###########################################
@@ -316,11 +316,11 @@
316 }
317
318 fossil revert
319 test rm-soft-absolute-4 {
320 [normalize_result] eq \
321 "REVERT subdirB/f9\nREVERT subdirC/f10\nREVERT subdirC/f11${undoMsg}"
322 }
323
324 cd $rootDir
325
326 ######################################
@@ -333,11 +333,11 @@
333 fossil rm [file join $rootDir f6]
334 test rm-soft-absolute-5 {$RESULT eq "DELETED f6"}
335
336 fossil revert
337 test rm-soft-absolute-6 {
338 [normalize_result] eq "REVERT f6${undoMsg}"
339 }
340
341 cd $rootDir
342
343 ###########################################
@@ -364,11 +364,11 @@
364 }
365
366 fossil revert
367 test rm-hard-absolute-4 {
368 [normalize_result] eq \
369 "REVERT subdirB/f9\nREVERT subdirC/f10\nREVERT subdirC/f11${undoMsg}"
370 }
371
372 cd $rootDir
373
374 ######################################
@@ -383,9 +383,9 @@
383 [normalize_result] eq "DELETED f8\nDELETED_FILE ${rootDir}/f8"
384 }
385
386 fossil revert
387 test rm-hard-absolute-6 {
388 [normalize_result] eq "REVERT f8${undoMsg}"
389 }
390
391 cd $rootDir
392
+18 -18
--- test/revert.test
+++ test/revert.test
@@ -70,41 +70,41 @@
7070
fossil mv f3 f3n
7171
7272
# Test 'fossil revert' with no arguments
7373
#
7474
revert-test 1-1 {} {
75
- UNMANAGE: f0
76
- REVERTED: f1
77
- REVERTED: f2
78
- REVERTED: f3
79
- DELETE: f3n
75
+ UNMANAGE f0
76
+ REVERT f1
77
+ REVERT f2
78
+ REVERT f3
79
+ DELETE f3n
8080
} -addremove {
8181
ADDED f0
8282
} -exists {f0 f1 f2 f3} -notexists f3n
8383
8484
# Test with a single filename argument
8585
#
8686
revert-test 1-2 f0 {
87
- UNMANAGE: f0
87
+ UNMANAGE f0
8888
} -changes {
8989
DELETED f1
9090
EDITED f2
9191
RENAMED f3n
9292
} -addremove {
9393
ADDED f0
9494
} -exists {f0 f2 f3n} -notexists f3
9595
9696
revert-test 1-3 f1 {
97
- REVERTED: f1
97
+ REVERT f1
9898
} -changes {
9999
ADDED f0
100100
EDITED f2
101101
RENAMED f3n
102102
} -exists {f0 f1 f2 f3n} -notexists f3
103103
104104
revert-test 1-4 f2 {
105
- REVERTED: f2
105
+ REVERT f2
106106
} -changes {
107107
ADDED f0
108108
DELETED f1
109109
RENAMED f3n
110110
} -exists {f0 f2 f3n} -notexists {f1 f3}
@@ -111,34 +111,34 @@
111111
112112
# Both files involved in a rename are reverted regardless of which filename
113113
# is used as an argument to 'fossil revert'
114114
#
115115
revert-test 1-5 f3 {
116
- REVERTED: f3
117
- DELETE: f3n
116
+ REVERT f3
117
+ DELETE f3n
118118
} -changes {
119119
ADDED f0
120120
DELETED f1
121121
EDITED f2
122122
} -exists {f0 f2 f3} -notexists {f1 f3n}
123123
124124
revert-test 1-6 f3n {
125
- REVERTED: f3
126
- DELETE: f3n
125
+ REVERT f3
126
+ DELETE f3n
127127
} -changes {
128128
ADDED f0
129129
DELETED f1
130130
EDITED f2
131131
} -exists {f0 f2 f3} -notexists {f1 f3n}
132132
133133
# Test with multiple filename arguments
134134
#
135135
revert-test 1-7 {f0 f2 f3n} {
136
- UNMANAGE: f0
137
- REVERTED: f2
138
- REVERTED: f3
139
- DELETE: f3n
136
+ UNMANAGE f0
137
+ REVERT f2
138
+ REVERT f3
139
+ DELETE f3n
140140
} -changes {
141141
DELETED f1
142142
} -addremove {
143143
ADDED f0
144144
} -exists {f0 f2 f3} -notexists {f1 f3n}
@@ -156,8 +156,8 @@
156156
fossil mv f1 f1n
157157
write_file f1 "f1b"
158158
fossil add f1
159159
160160
revert-test 2-1 {} {
161
- REVERTED: f1
162
- DELETE: f1n
161
+ REVERT f1
162
+ DELETE f1n
163163
} -exists {f1} -notexists {f1n}
164164
--- test/revert.test
+++ test/revert.test
@@ -70,41 +70,41 @@
70 fossil mv f3 f3n
71
72 # Test 'fossil revert' with no arguments
73 #
74 revert-test 1-1 {} {
75 UNMANAGE: f0
76 REVERTED: f1
77 REVERTED: f2
78 REVERTED: f3
79 DELETE: f3n
80 } -addremove {
81 ADDED f0
82 } -exists {f0 f1 f2 f3} -notexists f3n
83
84 # Test with a single filename argument
85 #
86 revert-test 1-2 f0 {
87 UNMANAGE: f0
88 } -changes {
89 DELETED f1
90 EDITED f2
91 RENAMED f3n
92 } -addremove {
93 ADDED f0
94 } -exists {f0 f2 f3n} -notexists f3
95
96 revert-test 1-3 f1 {
97 REVERTED: f1
98 } -changes {
99 ADDED f0
100 EDITED f2
101 RENAMED f3n
102 } -exists {f0 f1 f2 f3n} -notexists f3
103
104 revert-test 1-4 f2 {
105 REVERTED: f2
106 } -changes {
107 ADDED f0
108 DELETED f1
109 RENAMED f3n
110 } -exists {f0 f2 f3n} -notexists {f1 f3}
@@ -111,34 +111,34 @@
111
112 # Both files involved in a rename are reverted regardless of which filename
113 # is used as an argument to 'fossil revert'
114 #
115 revert-test 1-5 f3 {
116 REVERTED: f3
117 DELETE: f3n
118 } -changes {
119 ADDED f0
120 DELETED f1
121 EDITED f2
122 } -exists {f0 f2 f3} -notexists {f1 f3n}
123
124 revert-test 1-6 f3n {
125 REVERTED: f3
126 DELETE: f3n
127 } -changes {
128 ADDED f0
129 DELETED f1
130 EDITED f2
131 } -exists {f0 f2 f3} -notexists {f1 f3n}
132
133 # Test with multiple filename arguments
134 #
135 revert-test 1-7 {f0 f2 f3n} {
136 UNMANAGE: f0
137 REVERTED: f2
138 REVERTED: f3
139 DELETE: f3n
140 } -changes {
141 DELETED f1
142 } -addremove {
143 ADDED f0
144 } -exists {f0 f2 f3} -notexists {f1 f3n}
@@ -156,8 +156,8 @@
156 fossil mv f1 f1n
157 write_file f1 "f1b"
158 fossil add f1
159
160 revert-test 2-1 {} {
161 REVERTED: f1
162 DELETE: f1n
163 } -exists {f1} -notexists {f1n}
164
--- test/revert.test
+++ test/revert.test
@@ -70,41 +70,41 @@
70 fossil mv f3 f3n
71
72 # Test 'fossil revert' with no arguments
73 #
74 revert-test 1-1 {} {
75 UNMANAGE f0
76 REVERT f1
77 REVERT f2
78 REVERT f3
79 DELETE f3n
80 } -addremove {
81 ADDED f0
82 } -exists {f0 f1 f2 f3} -notexists f3n
83
84 # Test with a single filename argument
85 #
86 revert-test 1-2 f0 {
87 UNMANAGE f0
88 } -changes {
89 DELETED f1
90 EDITED f2
91 RENAMED f3n
92 } -addremove {
93 ADDED f0
94 } -exists {f0 f2 f3n} -notexists f3
95
96 revert-test 1-3 f1 {
97 REVERT f1
98 } -changes {
99 ADDED f0
100 EDITED f2
101 RENAMED f3n
102 } -exists {f0 f1 f2 f3n} -notexists f3
103
104 revert-test 1-4 f2 {
105 REVERT f2
106 } -changes {
107 ADDED f0
108 DELETED f1
109 RENAMED f3n
110 } -exists {f0 f2 f3n} -notexists {f1 f3}
@@ -111,34 +111,34 @@
111
112 # Both files involved in a rename are reverted regardless of which filename
113 # is used as an argument to 'fossil revert'
114 #
115 revert-test 1-5 f3 {
116 REVERT f3
117 DELETE f3n
118 } -changes {
119 ADDED f0
120 DELETED f1
121 EDITED f2
122 } -exists {f0 f2 f3} -notexists {f1 f3n}
123
124 revert-test 1-6 f3n {
125 REVERT f3
126 DELETE f3n
127 } -changes {
128 ADDED f0
129 DELETED f1
130 EDITED f2
131 } -exists {f0 f2 f3} -notexists {f1 f3n}
132
133 # Test with multiple filename arguments
134 #
135 revert-test 1-7 {f0 f2 f3n} {
136 UNMANAGE f0
137 REVERT f2
138 REVERT f3
139 DELETE f3n
140 } -changes {
141 DELETED f1
142 } -addremove {
143 ADDED f0
144 } -exists {f0 f2 f3} -notexists {f1 f3n}
@@ -156,8 +156,8 @@
156 fossil mv f1 f1n
157 write_file f1 "f1b"
158 fossil add f1
159
160 revert-test 2-1 {} {
161 REVERT f1
162 DELETE f1n
163 } -exists {f1} -notexists {f1n}
164
+39 -19
--- test/tester.tcl
+++ test/tester.tcl
@@ -49,25 +49,26 @@
4949
set VERBOSE 1
5050
set argv [lreplace $argv $i $i]
5151
} else {
5252
set VERBOSE 0
5353
}
54
+
55
+set i [lsearch $argv -quiet]
56
+if {$i>=0} {
57
+ set QUIET 1
58
+ set argv [lreplace $argv $i $i]
59
+} else {
60
+ set QUIET 0
61
+}
5462
5563
if {[llength $argv]==0} {
5664
foreach f [lsort [glob $testdir/*.test]] {
5765
set base [file root [file tail $f]]
5866
lappend argv $base
5967
}
6068
}
6169
62
-set tempPath [expr {[info exists env(TEMP)] ? \
63
- $env(TEMP) : [file dirname [info script]]}]
64
-
65
-if {$tcl_platform(platform) eq "windows"} then {
66
- set tempPath [string map [list \\ /] $tempPath]
67
-}
68
-
6970
# start protocol
7071
#
7172
proc protInit {cmd} {
7273
if {$::PROT} {
7374
set out [open [file join $::testrundir prot] w]
@@ -77,12 +78,14 @@
7778
}
7879
}
7980
8081
# write protocol
8182
#
82
-proc protOut {msg} {
83
- puts stdout $msg
83
+proc protOut {msg {noQuiet 0}} {
84
+ if {$noQuiet || !$::QUIET} {
85
+ puts stdout $msg
86
+ }
8487
if {$::PROT} {
8588
set out [open [file join $::testrundir prot] a]
8689
fconfigure $out -translation platform
8790
puts $out $msg
8891
close $out
@@ -126,11 +129,11 @@
126129
set rc [catch {eval exec $cmd} result]
127130
}
128131
global RESULT CODE
129132
set CODE $rc
130133
if {$rc} {
131
- protOut "ERROR: $result"
134
+ protOut "ERROR: $result" 1
132135
} elseif {$::VERBOSE} {
133136
protOut "RESULT: $result"
134137
}
135138
set RESULT $result
136139
}
@@ -207,12 +210,12 @@
207210
set expected [normalize_status_list $expected]
208211
set result [normalize_status_list $result]
209212
if {$result eq $expected} {
210213
test $name 1
211214
} else {
212
- protOut " Expected:\n [join $expected "\n "]"
213
- protOut " Got:\n [join $result "\n "]"
215
+ protOut " Expected:\n [join $expected "\n "]" 1
216
+ protOut " Got:\n [join $result "\n "]" 1
214217
test $name 0
215218
}
216219
}
217220
218221
# Append all arguments into a single value and then returns it.
@@ -254,11 +257,11 @@
254257
# Saves the TH1 setup script file by renaming it, based on the current
255258
# process ID.
256259
#
257260
proc saveTh1SetupFile {} {
258261
set oldFileName [getTh1SetupFileName]
259
- if {[file exists $oldFileName]} then {
262
+ if {[file exists $oldFileName]} {
260263
set newFileName [getSavedTh1SetupFileName]
261264
catch {file delete $newFileName}
262265
file rename $oldFileName $newFileName
263266
}
264267
}
@@ -267,11 +270,11 @@
267270
# on the current process ID.
268271
#
269272
proc restoreTh1SetupFile {} {
270273
set oldFileName [getSavedTh1SetupFileName]
271274
set newFileName [getTh1SetupFileName]
272
- if {[file exists $oldFileName]} then {
275
+ if {[file exists $oldFileName]} {
273276
catch {file delete $newFileName}
274277
file rename $oldFileName $newFileName
275278
} else {
276279
#
277280
# NOTE: There was no TH1 setup script file, delete the test one.
@@ -282,17 +285,18 @@
282285
283286
# Perform a test
284287
#
285288
set test_count 0
286289
proc test {name expr} {
287
- global bad_test test_count
290
+ global bad_test test_count RESULT
288291
incr test_count
289292
set r [uplevel 1 [list expr $expr]]
290293
if {$r} {
291294
protOut "test $name OK"
292295
} else {
293
- protOut "test $name FAILED!"
296
+ protOut "test $name FAILED!" 1
297
+ if {$::QUIET} {protOut "RESULT: $RESULT" 1}
294298
lappend bad_test $name
295299
if {$::HALT} exit
296300
}
297301
}
298302
set bad_test {}
@@ -367,11 +371,11 @@
367371
368372
write_file $inFileName $data
369373
fossil http $inFileName $outFileName 127.0.0.1 $repository --localauth
370374
set result [expr {[file exists $outFileName] ? [read_file $outFileName] : ""}]
371375
372
- if {1} then {
376
+ if {1} {
373377
catch {file delete $inFileName}
374378
catch {file delete $outFileName}
375379
}
376380
377381
return $result
@@ -418,10 +422,24 @@
418422
419423
# returns the third to last line of the normalized result.
420424
proc third_to_last_data_line {} {
421425
return [lindex [split [normalize_result] \n] end-2]
422426
}
427
+
428
+set tempPath [expr {[info exists env(TEMP)] ? \
429
+ $env(TEMP) : [file dirname [info script]]}]
430
+
431
+if {$tcl_platform(platform) eq "windows"} {
432
+ set tempPath [string map [list \\ /] $tempPath]
433
+}
434
+
435
+if {[catch {
436
+ write_file [file join $tempPath temporary.txt] [clock seconds]
437
+} error] != 0} {
438
+ error "could not write file to directory \"$tempPath\",\
439
+please set TEMP variable in environment: $error"
440
+}
423441
424442
protInit $fossilexe
425443
foreach testfile $argv {
426444
set dir [file root [file tail $testfile]]
427445
file delete -force $dir
@@ -432,9 +450,11 @@
432450
source $testdir/$testfile.test
433451
protOut "***** End of $testfile: [llength $bad_test] errors so far ******"
434452
cd $origwd
435453
}
436454
set nErr [llength $bad_test]
437
-protOut "***** Final result: $nErr errors out of $test_count tests"
455
+if {$nErr>0 || !$::QUIET} {
456
+ protOut "***** Final result: $nErr errors out of $test_count tests" 1
457
+}
438458
if {$nErr>0} {
439
- protOut "***** Failures: $bad_test"
459
+ protOut "***** Failures: $bad_test" 1
440460
}
441461
--- test/tester.tcl
+++ test/tester.tcl
@@ -49,25 +49,26 @@
49 set VERBOSE 1
50 set argv [lreplace $argv $i $i]
51 } else {
52 set VERBOSE 0
53 }
 
 
 
 
 
 
 
 
54
55 if {[llength $argv]==0} {
56 foreach f [lsort [glob $testdir/*.test]] {
57 set base [file root [file tail $f]]
58 lappend argv $base
59 }
60 }
61
62 set tempPath [expr {[info exists env(TEMP)] ? \
63 $env(TEMP) : [file dirname [info script]]}]
64
65 if {$tcl_platform(platform) eq "windows"} then {
66 set tempPath [string map [list \\ /] $tempPath]
67 }
68
69 # start protocol
70 #
71 proc protInit {cmd} {
72 if {$::PROT} {
73 set out [open [file join $::testrundir prot] w]
@@ -77,12 +78,14 @@
77 }
78 }
79
80 # write protocol
81 #
82 proc protOut {msg} {
83 puts stdout $msg
 
 
84 if {$::PROT} {
85 set out [open [file join $::testrundir prot] a]
86 fconfigure $out -translation platform
87 puts $out $msg
88 close $out
@@ -126,11 +129,11 @@
126 set rc [catch {eval exec $cmd} result]
127 }
128 global RESULT CODE
129 set CODE $rc
130 if {$rc} {
131 protOut "ERROR: $result"
132 } elseif {$::VERBOSE} {
133 protOut "RESULT: $result"
134 }
135 set RESULT $result
136 }
@@ -207,12 +210,12 @@
207 set expected [normalize_status_list $expected]
208 set result [normalize_status_list $result]
209 if {$result eq $expected} {
210 test $name 1
211 } else {
212 protOut " Expected:\n [join $expected "\n "]"
213 protOut " Got:\n [join $result "\n "]"
214 test $name 0
215 }
216 }
217
218 # Append all arguments into a single value and then returns it.
@@ -254,11 +257,11 @@
254 # Saves the TH1 setup script file by renaming it, based on the current
255 # process ID.
256 #
257 proc saveTh1SetupFile {} {
258 set oldFileName [getTh1SetupFileName]
259 if {[file exists $oldFileName]} then {
260 set newFileName [getSavedTh1SetupFileName]
261 catch {file delete $newFileName}
262 file rename $oldFileName $newFileName
263 }
264 }
@@ -267,11 +270,11 @@
267 # on the current process ID.
268 #
269 proc restoreTh1SetupFile {} {
270 set oldFileName [getSavedTh1SetupFileName]
271 set newFileName [getTh1SetupFileName]
272 if {[file exists $oldFileName]} then {
273 catch {file delete $newFileName}
274 file rename $oldFileName $newFileName
275 } else {
276 #
277 # NOTE: There was no TH1 setup script file, delete the test one.
@@ -282,17 +285,18 @@
282
283 # Perform a test
284 #
285 set test_count 0
286 proc test {name expr} {
287 global bad_test test_count
288 incr test_count
289 set r [uplevel 1 [list expr $expr]]
290 if {$r} {
291 protOut "test $name OK"
292 } else {
293 protOut "test $name FAILED!"
 
294 lappend bad_test $name
295 if {$::HALT} exit
296 }
297 }
298 set bad_test {}
@@ -367,11 +371,11 @@
367
368 write_file $inFileName $data
369 fossil http $inFileName $outFileName 127.0.0.1 $repository --localauth
370 set result [expr {[file exists $outFileName] ? [read_file $outFileName] : ""}]
371
372 if {1} then {
373 catch {file delete $inFileName}
374 catch {file delete $outFileName}
375 }
376
377 return $result
@@ -418,10 +422,24 @@
418
419 # returns the third to last line of the normalized result.
420 proc third_to_last_data_line {} {
421 return [lindex [split [normalize_result] \n] end-2]
422 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
423
424 protInit $fossilexe
425 foreach testfile $argv {
426 set dir [file root [file tail $testfile]]
427 file delete -force $dir
@@ -432,9 +450,11 @@
432 source $testdir/$testfile.test
433 protOut "***** End of $testfile: [llength $bad_test] errors so far ******"
434 cd $origwd
435 }
436 set nErr [llength $bad_test]
437 protOut "***** Final result: $nErr errors out of $test_count tests"
 
 
438 if {$nErr>0} {
439 protOut "***** Failures: $bad_test"
440 }
441
--- test/tester.tcl
+++ test/tester.tcl
@@ -49,25 +49,26 @@
49 set VERBOSE 1
50 set argv [lreplace $argv $i $i]
51 } else {
52 set VERBOSE 0
53 }
54
55 set i [lsearch $argv -quiet]
56 if {$i>=0} {
57 set QUIET 1
58 set argv [lreplace $argv $i $i]
59 } else {
60 set QUIET 0
61 }
62
63 if {[llength $argv]==0} {
64 foreach f [lsort [glob $testdir/*.test]] {
65 set base [file root [file tail $f]]
66 lappend argv $base
67 }
68 }
69
 
 
 
 
 
 
 
70 # start protocol
71 #
72 proc protInit {cmd} {
73 if {$::PROT} {
74 set out [open [file join $::testrundir prot] w]
@@ -77,12 +78,14 @@
78 }
79 }
80
81 # write protocol
82 #
83 proc protOut {msg {noQuiet 0}} {
84 if {$noQuiet || !$::QUIET} {
85 puts stdout $msg
86 }
87 if {$::PROT} {
88 set out [open [file join $::testrundir prot] a]
89 fconfigure $out -translation platform
90 puts $out $msg
91 close $out
@@ -126,11 +129,11 @@
129 set rc [catch {eval exec $cmd} result]
130 }
131 global RESULT CODE
132 set CODE $rc
133 if {$rc} {
134 protOut "ERROR: $result" 1
135 } elseif {$::VERBOSE} {
136 protOut "RESULT: $result"
137 }
138 set RESULT $result
139 }
@@ -207,12 +210,12 @@
210 set expected [normalize_status_list $expected]
211 set result [normalize_status_list $result]
212 if {$result eq $expected} {
213 test $name 1
214 } else {
215 protOut " Expected:\n [join $expected "\n "]" 1
216 protOut " Got:\n [join $result "\n "]" 1
217 test $name 0
218 }
219 }
220
221 # Append all arguments into a single value and then returns it.
@@ -254,11 +257,11 @@
257 # Saves the TH1 setup script file by renaming it, based on the current
258 # process ID.
259 #
260 proc saveTh1SetupFile {} {
261 set oldFileName [getTh1SetupFileName]
262 if {[file exists $oldFileName]} {
263 set newFileName [getSavedTh1SetupFileName]
264 catch {file delete $newFileName}
265 file rename $oldFileName $newFileName
266 }
267 }
@@ -267,11 +270,11 @@
270 # on the current process ID.
271 #
272 proc restoreTh1SetupFile {} {
273 set oldFileName [getSavedTh1SetupFileName]
274 set newFileName [getTh1SetupFileName]
275 if {[file exists $oldFileName]} {
276 catch {file delete $newFileName}
277 file rename $oldFileName $newFileName
278 } else {
279 #
280 # NOTE: There was no TH1 setup script file, delete the test one.
@@ -282,17 +285,18 @@
285
286 # Perform a test
287 #
288 set test_count 0
289 proc test {name expr} {
290 global bad_test test_count RESULT
291 incr test_count
292 set r [uplevel 1 [list expr $expr]]
293 if {$r} {
294 protOut "test $name OK"
295 } else {
296 protOut "test $name FAILED!" 1
297 if {$::QUIET} {protOut "RESULT: $RESULT" 1}
298 lappend bad_test $name
299 if {$::HALT} exit
300 }
301 }
302 set bad_test {}
@@ -367,11 +371,11 @@
371
372 write_file $inFileName $data
373 fossil http $inFileName $outFileName 127.0.0.1 $repository --localauth
374 set result [expr {[file exists $outFileName] ? [read_file $outFileName] : ""}]
375
376 if {1} {
377 catch {file delete $inFileName}
378 catch {file delete $outFileName}
379 }
380
381 return $result
@@ -418,10 +422,24 @@
422
423 # returns the third to last line of the normalized result.
424 proc third_to_last_data_line {} {
425 return [lindex [split [normalize_result] \n] end-2]
426 }
427
428 set tempPath [expr {[info exists env(TEMP)] ? \
429 $env(TEMP) : [file dirname [info script]]}]
430
431 if {$tcl_platform(platform) eq "windows"} {
432 set tempPath [string map [list \\ /] $tempPath]
433 }
434
435 if {[catch {
436 write_file [file join $tempPath temporary.txt] [clock seconds]
437 } error] != 0} {
438 error "could not write file to directory \"$tempPath\",\
439 please set TEMP variable in environment: $error"
440 }
441
442 protInit $fossilexe
443 foreach testfile $argv {
444 set dir [file root [file tail $testfile]]
445 file delete -force $dir
@@ -432,9 +450,11 @@
450 source $testdir/$testfile.test
451 protOut "***** End of $testfile: [llength $bad_test] errors so far ******"
452 cd $origwd
453 }
454 set nErr [llength $bad_test]
455 if {$nErr>0 || !$::QUIET} {
456 protOut "***** Final result: $nErr errors out of $test_count tests" 1
457 }
458 if {$nErr>0} {
459 protOut "***** Failures: $bad_test" 1
460 }
461
--- test/th1.test
+++ test/th1.test
@@ -1203,11 +1203,10 @@
12031203
###############################################################################
12041204
12051205
fossil test-th-eval {markdown "Test1\n=====\n*This is a test.*"}
12061206
test th1-markdown-4 {[normalize_result] eq {Test1 {<div class="markdown">
12071207
1208
-<h1>Test1</h1>
12091208
<p><em>This is a test.</em></p>
12101209
12111210
</div>
12121211
}}}
12131212
@@ -1217,11 +1216,10 @@
12171216
fossil test-th-eval [string map \
12181217
[list %markdown% $markdown] {markdown {%markdown%}}]
12191218
test th1-markdown-5 {[normalize_result] eq \
12201219
{{Markdown Formatter Test Document} {<div class="markdown">
12211220
1222
-<h1>Markdown Formatter Test Document</h1>
12231221
<p>This document is designed to test the markdown formatter.</p>
12241222
12251223
<ul>
12261224
<li>A bullet item.
12271225
12281226
--- test/th1.test
+++ test/th1.test
@@ -1203,11 +1203,10 @@
1203 ###############################################################################
1204
1205 fossil test-th-eval {markdown "Test1\n=====\n*This is a test.*"}
1206 test th1-markdown-4 {[normalize_result] eq {Test1 {<div class="markdown">
1207
1208 <h1>Test1</h1>
1209 <p><em>This is a test.</em></p>
1210
1211 </div>
1212 }}}
1213
@@ -1217,11 +1216,10 @@
1217 fossil test-th-eval [string map \
1218 [list %markdown% $markdown] {markdown {%markdown%}}]
1219 test th1-markdown-5 {[normalize_result] eq \
1220 {{Markdown Formatter Test Document} {<div class="markdown">
1221
1222 <h1>Markdown Formatter Test Document</h1>
1223 <p>This document is designed to test the markdown formatter.</p>
1224
1225 <ul>
1226 <li>A bullet item.
1227
1228
--- test/th1.test
+++ test/th1.test
@@ -1203,11 +1203,10 @@
1203 ###############################################################################
1204
1205 fossil test-th-eval {markdown "Test1\n=====\n*This is a test.*"}
1206 test th1-markdown-4 {[normalize_result] eq {Test1 {<div class="markdown">
1207
 
1208 <p><em>This is a test.</em></p>
1209
1210 </div>
1211 }}}
1212
@@ -1217,11 +1216,10 @@
1216 fossil test-th-eval [string map \
1217 [list %markdown% $markdown] {markdown {%markdown%}}]
1218 test th1-markdown-5 {[normalize_result] eq \
1219 {{Markdown Formatter Test Document} {<div class="markdown">
1220
 
1221 <p>This document is designed to test the markdown formatter.</p>
1222
1223 <ul>
1224 <li>A bullet item.
1225
1226
+5 -3
--- www/index.wiki
+++ www/index.wiki
@@ -120,13 +120,15 @@
120120
hosted on Fossil.
121121
* How to [./shunning.wiki | delete content] from a Fossil repository.
122122
* How Fossil does [./password.wiki | password management].
123123
* On-line [/help | help].
124124
* Documentation on the
125
- [http://www.sqliteconcepts.org/THManual.pdf | TH1 scripting language] used
126
- to configure the ticketing subsystem and the [./th1.md | extra commands]
127
- provided by Fossil itself.
125
+ [http://www.sqliteconcepts.org/THManual.pdf | TH1 scripting language],
126
+ used to customize [./custom_ticket.wiki | ticketing], and several other
127
+ subsystems, including [./customskin.md | theming].
128
+ * List of [./th1.md | TH1 commands provided by Fossil itself] that expose
129
+ its key functionality to TH1 scripts.
128130
* A free hosting server for Fossil repositories is available at
129131
[http://chiselapp.com/].
130132
* How to [./server.wiki | set up a server] for your repository.
131133
* Customizing the [./custom_ticket.wiki | ticket system].
132134
* Methods to [./checkin_names.wiki | identify a specific check-in].
133135
--- www/index.wiki
+++ www/index.wiki
@@ -120,13 +120,15 @@
120 hosted on Fossil.
121 * How to [./shunning.wiki | delete content] from a Fossil repository.
122 * How Fossil does [./password.wiki | password management].
123 * On-line [/help | help].
124 * Documentation on the
125 [http://www.sqliteconcepts.org/THManual.pdf | TH1 scripting language] used
126 to configure the ticketing subsystem and the [./th1.md | extra commands]
127 provided by Fossil itself.
 
 
128 * A free hosting server for Fossil repositories is available at
129 [http://chiselapp.com/].
130 * How to [./server.wiki | set up a server] for your repository.
131 * Customizing the [./custom_ticket.wiki | ticket system].
132 * Methods to [./checkin_names.wiki | identify a specific check-in].
133
--- www/index.wiki
+++ www/index.wiki
@@ -120,13 +120,15 @@
120 hosted on Fossil.
121 * How to [./shunning.wiki | delete content] from a Fossil repository.
122 * How Fossil does [./password.wiki | password management].
123 * On-line [/help | help].
124 * Documentation on the
125 [http://www.sqliteconcepts.org/THManual.pdf | TH1 scripting language],
126 used to customize [./custom_ticket.wiki | ticketing], and several other
127 subsystems, including [./customskin.md | theming].
128 * List of [./th1.md | TH1 commands provided by Fossil itself] that expose
129 its key functionality to TH1 scripts.
130 * A free hosting server for Fossil repositories is available at
131 [http://chiselapp.com/].
132 * How to [./server.wiki | set up a server] for your repository.
133 * Customizing the [./custom_ticket.wiki | ticket system].
134 * Methods to [./checkin_names.wiki | identify a specific check-in].
135

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button