Fossil SCM

Revamp the trigger used to captures changes to the EVENT table for use in other subsystems. The trigger is now a TEMP trigger rather than a persistent trigger. <b>Rebuild notice:</b> You can upgrade through this change without trouble, as the schema will adjust automatically. However, if you downgrade back through this change you must run rebuild to recreate the persistent triggers.

drh 2021-01-03 23:18 trunk
Commit 169ba8d4df37b9117d9699f6a50f2456f3eb968206477d17c4a43828e71439ce
+9 -8
--- src/alerts.c
+++ src/alerts.c
@@ -116,11 +116,10 @@
116116
&& fossil_strcmp(db_get("email-send-method",0),"off")==0
117117
){
118118
return; /* Don't create table for disabled email */
119119
}
120120
db_exec_sql(zAlertInit);
121
- alert_triggers_enable();
122121
}else if( !db_table_has_column("repository","pending_alert","sentMod") ){
123122
db_multi_exec(
124123
"ALTER TABLE repository.pending_alert"
125124
" ADD COLUMN sentMod BOOLEAN DEFAULT false;"
126125
);
@@ -129,15 +128,17 @@
129128
130129
/*
131130
** Enable triggers that automatically populate the pending_alert
132131
** table.
133132
*/
134
-void alert_triggers_enable(void){
133
+void alert_create_trigger(void){
135134
if( !db_table_exists("repository","pending_alert") ) return;
136135
db_multi_exec(
137
- "CREATE TRIGGER IF NOT EXISTS repository.alert_trigger1\n"
138
- "AFTER INSERT ON event BEGIN\n"
136
+ "DROP TRIGGER IF EXISTS repository.alert_trigger1;\n" /* Purge legacy */
137
+ /* "DROP TRIGGER IF EXISTS repository.email_trigger1;\n" Very old legacy */
138
+ "CREATE TRIGGER temp.alert_trigger1\n"
139
+ "AFTER INSERT ON repository.event BEGIN\n"
139140
" INSERT INTO pending_alert(eventid)\n"
140141
" SELECT printf('%%.1c%%d',new.type,new.objid) WHERE true\n"
141142
" ON CONFLICT(eventId) DO NOTHING;\n"
142143
"END;"
143144
);
@@ -147,14 +148,14 @@
147148
** Disable triggers the event_pending triggers.
148149
**
149150
** This must be called before rebuilding the EVENT table, for example
150151
** via the "fossil rebuild" command.
151152
*/
152
-void alert_triggers_disable(void){
153
+void alert_drop_trigger(void){
153154
db_multi_exec(
154
- "DROP TRIGGER IF EXISTS repository.alert_trigger1;\n"
155
- "DROP TRIGGER IF EXISTS repository.email_trigger1;\n" // Legacy
155
+ "DROP TRIGGER IF EXISTS temp.alert_trigger1;\n"
156
+ "DROP TRIGGER IF EXISTS repository.alert_trigger1;\n" /* Purge legacy */
156157
);
157158
}
158159
159160
/*
160161
** Return true if email alerts are active.
@@ -1062,11 +1063,11 @@
10621063
prompt_user("Continue? (y/N) ", &yn);
10631064
c = blob_str(&yn)[0];
10641065
blob_reset(&yn);
10651066
}
10661067
if( c=='y' ){
1067
- alert_triggers_disable();
1068
+ alert_drop_trigger();
10681069
db_multi_exec(
10691070
"DROP TABLE IF EXISTS subscriber;\n"
10701071
"DROP TABLE IF EXISTS pending_alert;\n"
10711072
"DROP TABLE IF EXISTS alert_bounce;\n"
10721073
/* Legacy */
10731074
--- src/alerts.c
+++ src/alerts.c
@@ -116,11 +116,10 @@
116 && fossil_strcmp(db_get("email-send-method",0),"off")==0
117 ){
118 return; /* Don't create table for disabled email */
119 }
120 db_exec_sql(zAlertInit);
121 alert_triggers_enable();
122 }else if( !db_table_has_column("repository","pending_alert","sentMod") ){
123 db_multi_exec(
124 "ALTER TABLE repository.pending_alert"
125 " ADD COLUMN sentMod BOOLEAN DEFAULT false;"
126 );
@@ -129,15 +128,17 @@
129
130 /*
131 ** Enable triggers that automatically populate the pending_alert
132 ** table.
133 */
134 void alert_triggers_enable(void){
135 if( !db_table_exists("repository","pending_alert") ) return;
136 db_multi_exec(
137 "CREATE TRIGGER IF NOT EXISTS repository.alert_trigger1\n"
138 "AFTER INSERT ON event BEGIN\n"
 
 
139 " INSERT INTO pending_alert(eventid)\n"
140 " SELECT printf('%%.1c%%d',new.type,new.objid) WHERE true\n"
141 " ON CONFLICT(eventId) DO NOTHING;\n"
142 "END;"
143 );
@@ -147,14 +148,14 @@
147 ** Disable triggers the event_pending triggers.
148 **
149 ** This must be called before rebuilding the EVENT table, for example
150 ** via the "fossil rebuild" command.
151 */
152 void alert_triggers_disable(void){
153 db_multi_exec(
154 "DROP TRIGGER IF EXISTS repository.alert_trigger1;\n"
155 "DROP TRIGGER IF EXISTS repository.email_trigger1;\n" // Legacy
156 );
157 }
158
159 /*
160 ** Return true if email alerts are active.
@@ -1062,11 +1063,11 @@
1062 prompt_user("Continue? (y/N) ", &yn);
1063 c = blob_str(&yn)[0];
1064 blob_reset(&yn);
1065 }
1066 if( c=='y' ){
1067 alert_triggers_disable();
1068 db_multi_exec(
1069 "DROP TABLE IF EXISTS subscriber;\n"
1070 "DROP TABLE IF EXISTS pending_alert;\n"
1071 "DROP TABLE IF EXISTS alert_bounce;\n"
1072 /* Legacy */
1073
--- src/alerts.c
+++ src/alerts.c
@@ -116,11 +116,10 @@
116 && fossil_strcmp(db_get("email-send-method",0),"off")==0
117 ){
118 return; /* Don't create table for disabled email */
119 }
120 db_exec_sql(zAlertInit);
 
121 }else if( !db_table_has_column("repository","pending_alert","sentMod") ){
122 db_multi_exec(
123 "ALTER TABLE repository.pending_alert"
124 " ADD COLUMN sentMod BOOLEAN DEFAULT false;"
125 );
@@ -129,15 +128,17 @@
128
129 /*
130 ** Enable triggers that automatically populate the pending_alert
131 ** table.
132 */
133 void alert_create_trigger(void){
134 if( !db_table_exists("repository","pending_alert") ) return;
135 db_multi_exec(
136 "DROP TRIGGER IF EXISTS repository.alert_trigger1;\n" /* Purge legacy */
137 /* "DROP TRIGGER IF EXISTS repository.email_trigger1;\n" Very old legacy */
138 "CREATE TRIGGER temp.alert_trigger1\n"
139 "AFTER INSERT ON repository.event BEGIN\n"
140 " INSERT INTO pending_alert(eventid)\n"
141 " SELECT printf('%%.1c%%d',new.type,new.objid) WHERE true\n"
142 " ON CONFLICT(eventId) DO NOTHING;\n"
143 "END;"
144 );
@@ -147,14 +148,14 @@
148 ** Disable triggers the event_pending triggers.
149 **
150 ** This must be called before rebuilding the EVENT table, for example
151 ** via the "fossil rebuild" command.
152 */
153 void alert_drop_trigger(void){
154 db_multi_exec(
155 "DROP TRIGGER IF EXISTS temp.alert_trigger1;\n"
156 "DROP TRIGGER IF EXISTS repository.alert_trigger1;\n" /* Purge legacy */
157 );
158 }
159
160 /*
161 ** Return true if email alerts are active.
@@ -1062,11 +1063,11 @@
1063 prompt_user("Continue? (y/N) ", &yn);
1064 c = blob_str(&yn)[0];
1065 blob_reset(&yn);
1066 }
1067 if( c=='y' ){
1068 alert_drop_trigger();
1069 db_multi_exec(
1070 "DROP TABLE IF EXISTS subscriber;\n"
1071 "DROP TABLE IF EXISTS pending_alert;\n"
1072 "DROP TABLE IF EXISTS alert_bounce;\n"
1073 /* Legacy */
1074
--- src/manifest.c
+++ src/manifest.c
@@ -168,10 +168,35 @@
168168
** True if manifest_crosslink_begin() has been called but
169169
** manifest_crosslink_end() is still pending.
170170
*/
171171
static int manifest_crosslink_busy = 0;
172172
173
+/*
174
+** There are some triggers that need to fire whenever new content
175
+** is added to the EVENT table, to make corresponding changes to the
176
+** PENDING_ALERT and CHAT tables. These are done with TEMP triggers
177
+** which are created as needed. The reasons for using TEMP triggers:
178
+**
179
+** * A small minority of invocations of Fossil need to use those triggers.
180
+** So we save CPU cycles in the common case by not having to parse the
181
+** trigger definition
182
+**
183
+** * We don't have to worry about dangling table references inside
184
+** of triggers. For example, we can create a trigger that adds
185
+** to the CHAT table. But an admin can still drop that CHAT table
186
+** at any moment, since the trigger that refers to CHAT is a TEMP
187
+** trigger and won't persist to cause problems.
188
+**
189
+** * Because TEMP triggers are defined by the specific version of the
190
+** application that is running, we don't have to worry with legacy
191
+** compatibility of the triggers.
192
+**
193
+** This boolean variable is set when the TEMP triggers for EVENT
194
+** have been created.
195
+*/
196
+static int manifest_event_triggers_are_enabled = 0;
197
+
173198
/*
174199
** Clear the memory allocated in a manifest object
175200
*/
176201
void manifest_destroy(Manifest *p){
177202
if( p ){
@@ -1938,10 +1963,11 @@
19381963
** by the call to manifest_crosslink_end().
19391964
*/
19401965
void manifest_crosslink_begin(void){
19411966
assert( manifest_crosslink_busy==0 );
19421967
manifest_crosslink_busy = 1;
1968
+ manifest_create_event_triggers();
19431969
db_begin_transaction();
19441970
db_multi_exec(
19451971
"CREATE TEMP TABLE pending_xlink(id TEXT PRIMARY KEY)WITHOUT ROWID;"
19461972
"CREATE TEMP TABLE time_fudge("
19471973
" mid INTEGER PRIMARY KEY," /* The rid of a manifest */
@@ -2056,10 +2082,32 @@
20562082
20572083
db_end_transaction(0);
20582084
manifest_crosslink_busy = 0;
20592085
return ( rc!=TH_ERROR );
20602086
}
2087
+
2088
+/*
2089
+** Activate EVENT triggers if they do not already exist.
2090
+*/
2091
+void manifest_create_event_triggers(void){
2092
+ if( manifest_event_triggers_are_enabled ){
2093
+ return; /* Triggers already exists. No-op. */
2094
+ }
2095
+ alert_create_trigger();
2096
+ manifest_event_triggers_are_enabled = 1;
2097
+}
2098
+
2099
+/*
2100
+** Disable manifest event triggers. Drop them if they exist, but mark
2101
+** them has having been created so that they won't be recreated. This
2102
+** is used during "rebuild" to prevent triggers from firing then.
2103
+*/
2104
+void manifest_disable_event_triggers(void){
2105
+ alert_drop_trigger();
2106
+ manifest_event_triggers_are_enabled = 1;
2107
+}
2108
+
20612109
20622110
/*
20632111
** Make an entry in the event table for a ticket change artifact.
20642112
*/
20652113
void manifest_ticket_event(
@@ -2126,10 +2174,11 @@
21262174
);
21272175
blob_appendf(&brief, "New ticket [%!S|%S].", pManifest->zTicketUuid,
21282176
pManifest->zTicketUuid);
21292177
}
21302178
fossil_free(zTitle);
2179
+ manifest_create_event_triggers();
21312180
db_multi_exec(
21322181
"REPLACE INTO event(type,tagid,mtime,objid,user,comment,brief)"
21332182
"VALUES('t',%d,%.17g,%d,%Q,%Q,%Q)",
21342183
tktTagId, pManifest->rDate, rid, pManifest->zUser,
21352184
blob_str(&comment), blob_str(&brief)
@@ -2227,10 +2276,11 @@
22272276
const char *zUuid = 0;
22282277
22292278
if( g.fSqlTrace ){
22302279
fossil_trace("-- manifest_crosslink(%d)\n", rid);
22312280
}
2281
+ manifest_create_event_triggers();
22322282
if( (p = manifest_cache_find(rid))!=0 ){
22332283
blob_reset(pContent);
22342284
}else if( (p = manifest_parse(pContent, rid, 0))==0 ){
22352285
assert( blob_is_reset(pContent) || pContent==0 );
22362286
if( (flags & MC_NO_ERRORS)==0 ){
@@ -2274,10 +2324,11 @@
22742324
}
22752325
if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
22762326
char *zCom;
22772327
parentid = manifest_add_checkin_linkages(rid,p,p->nParent,p->azParent);
22782328
search_doc_touch('c', rid, 0);
2329
+ assert( manifest_event_triggers_are_enabled );
22792330
db_multi_exec(
22802331
"REPLACE INTO event(type,mtime,objid,user,comment,"
22812332
"bgcolor,euser,ecomment,omtime)"
22822333
"VALUES('ci',"
22832334
" coalesce("
@@ -2389,10 +2440,11 @@
23892440
if( manifest_crosslink_busy ){
23902441
add_pending_crosslink('w',p->zWikiTitle);
23912442
}else{
23922443
backlink_wiki_refresh(p->zWikiTitle);
23932444
}
2445
+ assert( manifest_event_triggers_are_enabled );
23942446
db_multi_exec(
23952447
"REPLACE INTO event(type,mtime,objid,user,comment)"
23962448
"VALUES('w',%.17g,%d,%Q,'%c%q');",
23972449
p->rDate, rid, p->zUser, cPrefix, p->zWikiTitle
23982450
);
@@ -2435,10 +2487,11 @@
24352487
}
24362488
if( subsequent ){
24372489
content_deltify(rid, &subsequent, 1, 0);
24382490
}else{
24392491
search_doc_touch('e',rid,0);
2492
+ assert( manifest_event_triggers_are_enabled );
24402493
db_multi_exec(
24412494
"REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
24422495
"VALUES('e',%.17g,%d,%d,%Q,%Q,"
24432496
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
24442497
p->rEventDate, rid, tagid, p->zUser, p->zComment,
@@ -2575,10 +2628,11 @@
25752628
}else{
25762629
zComment = mprintf("Delete attachment \"%h\" from ticket [%!S|%S]",
25772630
p->zAttachName, p->zAttachTarget, p->zAttachTarget);
25782631
}
25792632
}
2633
+ assert( manifest_event_triggers_are_enabled );
25802634
db_multi_exec(
25812635
"REPLACE INTO event(type,mtime,objid,user,comment)"
25822636
"VALUES('%c',%.17g,%d,%Q,%Q)",
25832637
attachToType, p->rDate, rid, p->zUser, zComment
25842638
);
@@ -2678,10 +2732,11 @@
26782732
blob_appendf(&comment, ".");
26792733
}
26802734
}
26812735
/*blob_appendf(&comment, " &#91;[/info/%S | details]&#93;");*/
26822736
if( blob_size(&comment)==0 ) blob_append(&comment, " ", 1);
2737
+ assert( manifest_event_triggers_are_enabled );
26832738
db_multi_exec(
26842739
"REPLACE INTO event(type,mtime,objid,user,comment)"
26852740
"VALUES('g',%.17g,%d,%Q,%Q)",
26862741
p->rDate, rid, p->zUser, blob_str(&comment)+1
26872742
);
@@ -2707,10 +2762,11 @@
27072762
zTitle = p->zThreadTitle;
27082763
if( zTitle==0 || zTitle[0]==0 ){
27092764
zTitle = "(Deleted)";
27102765
}
27112766
zFType = fprev ? "Edit" : "Post";
2767
+ assert( manifest_event_triggers_are_enabled );
27122768
db_multi_exec(
27132769
"REPLACE INTO event(type,mtime,objid,user,comment)"
27142770
"VALUES('f',%.17g,%d,%Q,'%q: %q')",
27152771
p->rDate, rid, p->zUser, zFType, zTitle
27162772
);
@@ -2739,10 +2795,11 @@
27392795
}else if( fprev ){
27402796
zFType = "Edit reply";
27412797
}else{
27422798
zFType = "Reply";
27432799
}
2800
+ assert( manifest_event_triggers_are_enabled );
27442801
db_multi_exec(
27452802
"REPLACE INTO event(type,mtime,objid,user,comment)"
27462803
"VALUES('f',%.17g,%d,%Q,'%q: %q')",
27472804
p->rDate, rid, p->zUser, zFType, zTitle
27482805
);
27492806
--- src/manifest.c
+++ src/manifest.c
@@ -168,10 +168,35 @@
168 ** True if manifest_crosslink_begin() has been called but
169 ** manifest_crosslink_end() is still pending.
170 */
171 static int manifest_crosslink_busy = 0;
172
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173 /*
174 ** Clear the memory allocated in a manifest object
175 */
176 void manifest_destroy(Manifest *p){
177 if( p ){
@@ -1938,10 +1963,11 @@
1938 ** by the call to manifest_crosslink_end().
1939 */
1940 void manifest_crosslink_begin(void){
1941 assert( manifest_crosslink_busy==0 );
1942 manifest_crosslink_busy = 1;
 
1943 db_begin_transaction();
1944 db_multi_exec(
1945 "CREATE TEMP TABLE pending_xlink(id TEXT PRIMARY KEY)WITHOUT ROWID;"
1946 "CREATE TEMP TABLE time_fudge("
1947 " mid INTEGER PRIMARY KEY," /* The rid of a manifest */
@@ -2056,10 +2082,32 @@
2056
2057 db_end_transaction(0);
2058 manifest_crosslink_busy = 0;
2059 return ( rc!=TH_ERROR );
2060 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2061
2062 /*
2063 ** Make an entry in the event table for a ticket change artifact.
2064 */
2065 void manifest_ticket_event(
@@ -2126,10 +2174,11 @@
2126 );
2127 blob_appendf(&brief, "New ticket [%!S|%S].", pManifest->zTicketUuid,
2128 pManifest->zTicketUuid);
2129 }
2130 fossil_free(zTitle);
 
2131 db_multi_exec(
2132 "REPLACE INTO event(type,tagid,mtime,objid,user,comment,brief)"
2133 "VALUES('t',%d,%.17g,%d,%Q,%Q,%Q)",
2134 tktTagId, pManifest->rDate, rid, pManifest->zUser,
2135 blob_str(&comment), blob_str(&brief)
@@ -2227,10 +2276,11 @@
2227 const char *zUuid = 0;
2228
2229 if( g.fSqlTrace ){
2230 fossil_trace("-- manifest_crosslink(%d)\n", rid);
2231 }
 
2232 if( (p = manifest_cache_find(rid))!=0 ){
2233 blob_reset(pContent);
2234 }else if( (p = manifest_parse(pContent, rid, 0))==0 ){
2235 assert( blob_is_reset(pContent) || pContent==0 );
2236 if( (flags & MC_NO_ERRORS)==0 ){
@@ -2274,10 +2324,11 @@
2274 }
2275 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
2276 char *zCom;
2277 parentid = manifest_add_checkin_linkages(rid,p,p->nParent,p->azParent);
2278 search_doc_touch('c', rid, 0);
 
2279 db_multi_exec(
2280 "REPLACE INTO event(type,mtime,objid,user,comment,"
2281 "bgcolor,euser,ecomment,omtime)"
2282 "VALUES('ci',"
2283 " coalesce("
@@ -2389,10 +2440,11 @@
2389 if( manifest_crosslink_busy ){
2390 add_pending_crosslink('w',p->zWikiTitle);
2391 }else{
2392 backlink_wiki_refresh(p->zWikiTitle);
2393 }
 
2394 db_multi_exec(
2395 "REPLACE INTO event(type,mtime,objid,user,comment)"
2396 "VALUES('w',%.17g,%d,%Q,'%c%q');",
2397 p->rDate, rid, p->zUser, cPrefix, p->zWikiTitle
2398 );
@@ -2435,10 +2487,11 @@
2435 }
2436 if( subsequent ){
2437 content_deltify(rid, &subsequent, 1, 0);
2438 }else{
2439 search_doc_touch('e',rid,0);
 
2440 db_multi_exec(
2441 "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
2442 "VALUES('e',%.17g,%d,%d,%Q,%Q,"
2443 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
2444 p->rEventDate, rid, tagid, p->zUser, p->zComment,
@@ -2575,10 +2628,11 @@
2575 }else{
2576 zComment = mprintf("Delete attachment \"%h\" from ticket [%!S|%S]",
2577 p->zAttachName, p->zAttachTarget, p->zAttachTarget);
2578 }
2579 }
 
2580 db_multi_exec(
2581 "REPLACE INTO event(type,mtime,objid,user,comment)"
2582 "VALUES('%c',%.17g,%d,%Q,%Q)",
2583 attachToType, p->rDate, rid, p->zUser, zComment
2584 );
@@ -2678,10 +2732,11 @@
2678 blob_appendf(&comment, ".");
2679 }
2680 }
2681 /*blob_appendf(&comment, " &#91;[/info/%S | details]&#93;");*/
2682 if( blob_size(&comment)==0 ) blob_append(&comment, " ", 1);
 
2683 db_multi_exec(
2684 "REPLACE INTO event(type,mtime,objid,user,comment)"
2685 "VALUES('g',%.17g,%d,%Q,%Q)",
2686 p->rDate, rid, p->zUser, blob_str(&comment)+1
2687 );
@@ -2707,10 +2762,11 @@
2707 zTitle = p->zThreadTitle;
2708 if( zTitle==0 || zTitle[0]==0 ){
2709 zTitle = "(Deleted)";
2710 }
2711 zFType = fprev ? "Edit" : "Post";
 
2712 db_multi_exec(
2713 "REPLACE INTO event(type,mtime,objid,user,comment)"
2714 "VALUES('f',%.17g,%d,%Q,'%q: %q')",
2715 p->rDate, rid, p->zUser, zFType, zTitle
2716 );
@@ -2739,10 +2795,11 @@
2739 }else if( fprev ){
2740 zFType = "Edit reply";
2741 }else{
2742 zFType = "Reply";
2743 }
 
2744 db_multi_exec(
2745 "REPLACE INTO event(type,mtime,objid,user,comment)"
2746 "VALUES('f',%.17g,%d,%Q,'%q: %q')",
2747 p->rDate, rid, p->zUser, zFType, zTitle
2748 );
2749
--- src/manifest.c
+++ src/manifest.c
@@ -168,10 +168,35 @@
168 ** True if manifest_crosslink_begin() has been called but
169 ** manifest_crosslink_end() is still pending.
170 */
171 static int manifest_crosslink_busy = 0;
172
173 /*
174 ** There are some triggers that need to fire whenever new content
175 ** is added to the EVENT table, to make corresponding changes to the
176 ** PENDING_ALERT and CHAT tables. These are done with TEMP triggers
177 ** which are created as needed. The reasons for using TEMP triggers:
178 **
179 ** * A small minority of invocations of Fossil need to use those triggers.
180 ** So we save CPU cycles in the common case by not having to parse the
181 ** trigger definition
182 **
183 ** * We don't have to worry about dangling table references inside
184 ** of triggers. For example, we can create a trigger that adds
185 ** to the CHAT table. But an admin can still drop that CHAT table
186 ** at any moment, since the trigger that refers to CHAT is a TEMP
187 ** trigger and won't persist to cause problems.
188 **
189 ** * Because TEMP triggers are defined by the specific version of the
190 ** application that is running, we don't have to worry with legacy
191 ** compatibility of the triggers.
192 **
193 ** This boolean variable is set when the TEMP triggers for EVENT
194 ** have been created.
195 */
196 static int manifest_event_triggers_are_enabled = 0;
197
198 /*
199 ** Clear the memory allocated in a manifest object
200 */
201 void manifest_destroy(Manifest *p){
202 if( p ){
@@ -1938,10 +1963,11 @@
1963 ** by the call to manifest_crosslink_end().
1964 */
1965 void manifest_crosslink_begin(void){
1966 assert( manifest_crosslink_busy==0 );
1967 manifest_crosslink_busy = 1;
1968 manifest_create_event_triggers();
1969 db_begin_transaction();
1970 db_multi_exec(
1971 "CREATE TEMP TABLE pending_xlink(id TEXT PRIMARY KEY)WITHOUT ROWID;"
1972 "CREATE TEMP TABLE time_fudge("
1973 " mid INTEGER PRIMARY KEY," /* The rid of a manifest */
@@ -2056,10 +2082,32 @@
2082
2083 db_end_transaction(0);
2084 manifest_crosslink_busy = 0;
2085 return ( rc!=TH_ERROR );
2086 }
2087
2088 /*
2089 ** Activate EVENT triggers if they do not already exist.
2090 */
2091 void manifest_create_event_triggers(void){
2092 if( manifest_event_triggers_are_enabled ){
2093 return; /* Triggers already exists. No-op. */
2094 }
2095 alert_create_trigger();
2096 manifest_event_triggers_are_enabled = 1;
2097 }
2098
2099 /*
2100 ** Disable manifest event triggers. Drop them if they exist, but mark
2101 ** them has having been created so that they won't be recreated. This
2102 ** is used during "rebuild" to prevent triggers from firing then.
2103 */
2104 void manifest_disable_event_triggers(void){
2105 alert_drop_trigger();
2106 manifest_event_triggers_are_enabled = 1;
2107 }
2108
2109
2110 /*
2111 ** Make an entry in the event table for a ticket change artifact.
2112 */
2113 void manifest_ticket_event(
@@ -2126,10 +2174,11 @@
2174 );
2175 blob_appendf(&brief, "New ticket [%!S|%S].", pManifest->zTicketUuid,
2176 pManifest->zTicketUuid);
2177 }
2178 fossil_free(zTitle);
2179 manifest_create_event_triggers();
2180 db_multi_exec(
2181 "REPLACE INTO event(type,tagid,mtime,objid,user,comment,brief)"
2182 "VALUES('t',%d,%.17g,%d,%Q,%Q,%Q)",
2183 tktTagId, pManifest->rDate, rid, pManifest->zUser,
2184 blob_str(&comment), blob_str(&brief)
@@ -2227,10 +2276,11 @@
2276 const char *zUuid = 0;
2277
2278 if( g.fSqlTrace ){
2279 fossil_trace("-- manifest_crosslink(%d)\n", rid);
2280 }
2281 manifest_create_event_triggers();
2282 if( (p = manifest_cache_find(rid))!=0 ){
2283 blob_reset(pContent);
2284 }else if( (p = manifest_parse(pContent, rid, 0))==0 ){
2285 assert( blob_is_reset(pContent) || pContent==0 );
2286 if( (flags & MC_NO_ERRORS)==0 ){
@@ -2274,10 +2324,11 @@
2324 }
2325 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
2326 char *zCom;
2327 parentid = manifest_add_checkin_linkages(rid,p,p->nParent,p->azParent);
2328 search_doc_touch('c', rid, 0);
2329 assert( manifest_event_triggers_are_enabled );
2330 db_multi_exec(
2331 "REPLACE INTO event(type,mtime,objid,user,comment,"
2332 "bgcolor,euser,ecomment,omtime)"
2333 "VALUES('ci',"
2334 " coalesce("
@@ -2389,10 +2440,11 @@
2440 if( manifest_crosslink_busy ){
2441 add_pending_crosslink('w',p->zWikiTitle);
2442 }else{
2443 backlink_wiki_refresh(p->zWikiTitle);
2444 }
2445 assert( manifest_event_triggers_are_enabled );
2446 db_multi_exec(
2447 "REPLACE INTO event(type,mtime,objid,user,comment)"
2448 "VALUES('w',%.17g,%d,%Q,'%c%q');",
2449 p->rDate, rid, p->zUser, cPrefix, p->zWikiTitle
2450 );
@@ -2435,10 +2487,11 @@
2487 }
2488 if( subsequent ){
2489 content_deltify(rid, &subsequent, 1, 0);
2490 }else{
2491 search_doc_touch('e',rid,0);
2492 assert( manifest_event_triggers_are_enabled );
2493 db_multi_exec(
2494 "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
2495 "VALUES('e',%.17g,%d,%d,%Q,%Q,"
2496 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
2497 p->rEventDate, rid, tagid, p->zUser, p->zComment,
@@ -2575,10 +2628,11 @@
2628 }else{
2629 zComment = mprintf("Delete attachment \"%h\" from ticket [%!S|%S]",
2630 p->zAttachName, p->zAttachTarget, p->zAttachTarget);
2631 }
2632 }
2633 assert( manifest_event_triggers_are_enabled );
2634 db_multi_exec(
2635 "REPLACE INTO event(type,mtime,objid,user,comment)"
2636 "VALUES('%c',%.17g,%d,%Q,%Q)",
2637 attachToType, p->rDate, rid, p->zUser, zComment
2638 );
@@ -2678,10 +2732,11 @@
2732 blob_appendf(&comment, ".");
2733 }
2734 }
2735 /*blob_appendf(&comment, " &#91;[/info/%S | details]&#93;");*/
2736 if( blob_size(&comment)==0 ) blob_append(&comment, " ", 1);
2737 assert( manifest_event_triggers_are_enabled );
2738 db_multi_exec(
2739 "REPLACE INTO event(type,mtime,objid,user,comment)"
2740 "VALUES('g',%.17g,%d,%Q,%Q)",
2741 p->rDate, rid, p->zUser, blob_str(&comment)+1
2742 );
@@ -2707,10 +2762,11 @@
2762 zTitle = p->zThreadTitle;
2763 if( zTitle==0 || zTitle[0]==0 ){
2764 zTitle = "(Deleted)";
2765 }
2766 zFType = fprev ? "Edit" : "Post";
2767 assert( manifest_event_triggers_are_enabled );
2768 db_multi_exec(
2769 "REPLACE INTO event(type,mtime,objid,user,comment)"
2770 "VALUES('f',%.17g,%d,%Q,'%q: %q')",
2771 p->rDate, rid, p->zUser, zFType, zTitle
2772 );
@@ -2739,10 +2795,11 @@
2795 }else if( fprev ){
2796 zFType = "Edit reply";
2797 }else{
2798 zFType = "Reply";
2799 }
2800 assert( manifest_event_triggers_are_enabled );
2801 db_multi_exec(
2802 "REPLACE INTO event(type,mtime,objid,user,comment)"
2803 "VALUES('f',%.17g,%d,%Q,'%q: %q')",
2804 p->rDate, rid, p->zUser, zFType, zTitle
2805 );
2806
+1 -2
--- src/rebuild.c
+++ src/rebuild.c
@@ -383,11 +383,11 @@
383383
ttyOutput = doOut;
384384
processCnt = 0;
385385
if (ttyOutput && !g.fQuiet) {
386386
percent_complete(0);
387387
}
388
- alert_triggers_disable();
388
+ manifest_disable_event_triggers();
389389
rebuild_update_schema();
390390
blob_init(&sql, 0, 0);
391391
db_unprotect(PROTECT_ALL);
392392
db_prepare(&q,
393393
"SELECT name FROM sqlite_schema /*scan*/"
@@ -475,11 +475,10 @@
475475
if( doClustering ) create_cluster();
476476
if( ttyOutput && !g.fQuiet && totalSize>0 ){
477477
processCnt += incrSize;
478478
percent_complete((processCnt*1000)/totalSize);
479479
}
480
- alert_triggers_enable();
481480
if(!g.fQuiet && ttyOutput ){
482481
percent_complete(1000);
483482
fossil_print("\n");
484483
}
485484
db_protect_pop();
486485
--- src/rebuild.c
+++ src/rebuild.c
@@ -383,11 +383,11 @@
383 ttyOutput = doOut;
384 processCnt = 0;
385 if (ttyOutput && !g.fQuiet) {
386 percent_complete(0);
387 }
388 alert_triggers_disable();
389 rebuild_update_schema();
390 blob_init(&sql, 0, 0);
391 db_unprotect(PROTECT_ALL);
392 db_prepare(&q,
393 "SELECT name FROM sqlite_schema /*scan*/"
@@ -475,11 +475,10 @@
475 if( doClustering ) create_cluster();
476 if( ttyOutput && !g.fQuiet && totalSize>0 ){
477 processCnt += incrSize;
478 percent_complete((processCnt*1000)/totalSize);
479 }
480 alert_triggers_enable();
481 if(!g.fQuiet && ttyOutput ){
482 percent_complete(1000);
483 fossil_print("\n");
484 }
485 db_protect_pop();
486
--- src/rebuild.c
+++ src/rebuild.c
@@ -383,11 +383,11 @@
383 ttyOutput = doOut;
384 processCnt = 0;
385 if (ttyOutput && !g.fQuiet) {
386 percent_complete(0);
387 }
388 manifest_disable_event_triggers();
389 rebuild_update_schema();
390 blob_init(&sql, 0, 0);
391 db_unprotect(PROTECT_ALL);
392 db_prepare(&q,
393 "SELECT name FROM sqlite_schema /*scan*/"
@@ -475,11 +475,10 @@
475 if( doClustering ) create_cluster();
476 if( ttyOutput && !g.fQuiet && totalSize>0 ){
477 processCnt += incrSize;
478 percent_complete((processCnt*1000)/totalSize);
479 }
 
480 if(!g.fQuiet && ttyOutput ){
481 percent_complete(1000);
482 fossil_print("\n");
483 }
484 db_protect_pop();
485

Keyboard Shortcuts

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