Fossil SCM

Change compute_direct_ancestors() to use a recursive common table expression.

drh 2015-12-13 00:35 trunk
Commit 6599d097298da9e670df505a32618f1c78e752e7
2 files changed +10 -25 +2 -2
+10 -25
--- src/descendants.c
+++ src/descendants.c
@@ -180,44 +180,29 @@
180180
rid, rid, directOnly ? "AND plink.isPrim" : "", N
181181
);
182182
}
183183
184184
/*
185
-** Compute up to N direct ancestors (merge ancestors do not count)
185
+** Compute all direct ancestors (merge ancestors do not count)
186186
** for the check-in rid and put them in a table named "ancestor".
187187
** Label each generation with consecutive integers going backwards
188188
** in time such that rid has the smallest generation number and the oldest
189189
** direct ancestor as the largest generation number.
190190
*/
191
-void compute_direct_ancestors(int rid, int N){
192
- Stmt ins;
193
- Stmt q;
194
- int gen = 0;
191
+void compute_direct_ancestors(int rid){
195192
db_multi_exec(
196193
"CREATE TEMP TABLE IF NOT EXISTS ancestor(rid INTEGER UNIQUE NOT NULL,"
197194
" generation INTEGER PRIMARY KEY);"
198195
"DELETE FROM ancestor;"
199
- "INSERT INTO ancestor VALUES(%d, 0);", rid
200
- );
201
- db_prepare(&ins, "INSERT INTO ancestor VALUES(:rid, :gen)");
202
- db_prepare(&q,
203
- "SELECT pid FROM plink"
204
- " WHERE cid=:rid AND isprim"
205
- );
206
- while( (N--)>0 ){
207
- db_bind_int(&q, ":rid", rid);
208
- if( db_step(&q)!=SQLITE_ROW ) break;
209
- rid = db_column_int(&q, 0);
210
- db_reset(&q);
211
- gen++;
212
- db_bind_int(&ins, ":rid", rid);
213
- db_bind_int(&ins, ":gen", gen);
214
- db_step(&ins);
215
- db_reset(&ins);
216
- }
217
- db_finalize(&ins);
218
- db_finalize(&q);
196
+ "WITH RECURSIVE g(x,i) AS ("
197
+ " VALUES(%d,1)"
198
+ " UNION ALL"
199
+ " SELECT plink.pid, g.i+1 FROM plink, g"
200
+ " WHERE plink.cid=g.x AND plink.isprim)"
201
+ "INSERT INTO ancestor(rid,generation) SELECT x,i FROM g;",
202
+ rid
203
+ );
219204
}
220205
221206
/*
222207
** Compute the "mtime" of the file given whose blob.rid is "fid" that
223208
** is part of check-in "vid". The mtime will be the mtime on vid or
224209
--- src/descendants.c
+++ src/descendants.c
@@ -180,44 +180,29 @@
180 rid, rid, directOnly ? "AND plink.isPrim" : "", N
181 );
182 }
183
184 /*
185 ** Compute up to N direct ancestors (merge ancestors do not count)
186 ** for the check-in rid and put them in a table named "ancestor".
187 ** Label each generation with consecutive integers going backwards
188 ** in time such that rid has the smallest generation number and the oldest
189 ** direct ancestor as the largest generation number.
190 */
191 void compute_direct_ancestors(int rid, int N){
192 Stmt ins;
193 Stmt q;
194 int gen = 0;
195 db_multi_exec(
196 "CREATE TEMP TABLE IF NOT EXISTS ancestor(rid INTEGER UNIQUE NOT NULL,"
197 " generation INTEGER PRIMARY KEY);"
198 "DELETE FROM ancestor;"
199 "INSERT INTO ancestor VALUES(%d, 0);", rid
200 );
201 db_prepare(&ins, "INSERT INTO ancestor VALUES(:rid, :gen)");
202 db_prepare(&q,
203 "SELECT pid FROM plink"
204 " WHERE cid=:rid AND isprim"
205 );
206 while( (N--)>0 ){
207 db_bind_int(&q, ":rid", rid);
208 if( db_step(&q)!=SQLITE_ROW ) break;
209 rid = db_column_int(&q, 0);
210 db_reset(&q);
211 gen++;
212 db_bind_int(&ins, ":rid", rid);
213 db_bind_int(&ins, ":gen", gen);
214 db_step(&ins);
215 db_reset(&ins);
216 }
217 db_finalize(&ins);
218 db_finalize(&q);
219 }
220
221 /*
222 ** Compute the "mtime" of the file given whose blob.rid is "fid" that
223 ** is part of check-in "vid". The mtime will be the mtime on vid or
224
--- src/descendants.c
+++ src/descendants.c
@@ -180,44 +180,29 @@
180 rid, rid, directOnly ? "AND plink.isPrim" : "", N
181 );
182 }
183
184 /*
185 ** Compute all direct ancestors (merge ancestors do not count)
186 ** for the check-in rid and put them in a table named "ancestor".
187 ** Label each generation with consecutive integers going backwards
188 ** in time such that rid has the smallest generation number and the oldest
189 ** direct ancestor as the largest generation number.
190 */
191 void compute_direct_ancestors(int rid){
 
 
 
192 db_multi_exec(
193 "CREATE TEMP TABLE IF NOT EXISTS ancestor(rid INTEGER UNIQUE NOT NULL,"
194 " generation INTEGER PRIMARY KEY);"
195 "DELETE FROM ancestor;"
196 "WITH RECURSIVE g(x,i) AS ("
197 " VALUES(%d,1)"
198 " UNION ALL"
199 " SELECT plink.pid, g.i+1 FROM plink, g"
200 " WHERE plink.cid=g.x AND plink.isprim)"
201 "INSERT INTO ancestor(rid,generation) SELECT x,i FROM g;",
202 rid
203 );
 
 
 
 
 
 
 
 
 
 
 
 
204 }
205
206 /*
207 ** Compute the "mtime" of the file given whose blob.rid is "fid" that
208 ** is part of check-in "vid". The mtime will be the mtime on vid or
209
+2 -2
--- src/diff.c
+++ src/diff.c
@@ -2299,11 +2299,11 @@
22992299
if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
23002300
fossil_redirect_home();
23012301
}
23022302
23032303
/* compute the annotation */
2304
- compute_direct_ancestors(mid, 10000000);
2304
+ compute_direct_ancestors(mid);
23052305
annotate_file(&ann, fnid, mid, iLimit, annFlags);
23062306
zCI = ann.aVers[0].zMUuid;
23072307
23082308
/* generate the web page */
23092309
style_header("Annotation For %h", zFilename);
@@ -2505,11 +2505,11 @@
25052505
cid = db_lget_int("checkout", 0);
25062506
if( cid == 0 ){
25072507
fossil_fatal("Not in a checkout");
25082508
}
25092509
if( iLimit<=0 ) iLimit = 1000000000;
2510
- compute_direct_ancestors(cid, 1000000);
2510
+ compute_direct_ancestors(cid);
25112511
mid = db_int(0, "SELECT mlink.mid FROM mlink, ancestor "
25122512
" WHERE mlink.fid=%d AND mlink.fnid=%d AND mlink.mid=ancestor.rid"
25132513
" ORDER BY ancestor.generation ASC LIMIT 1",
25142514
fid, fnid);
25152515
if( mid==0 ){
25162516
--- src/diff.c
+++ src/diff.c
@@ -2299,11 +2299,11 @@
2299 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
2300 fossil_redirect_home();
2301 }
2302
2303 /* compute the annotation */
2304 compute_direct_ancestors(mid, 10000000);
2305 annotate_file(&ann, fnid, mid, iLimit, annFlags);
2306 zCI = ann.aVers[0].zMUuid;
2307
2308 /* generate the web page */
2309 style_header("Annotation For %h", zFilename);
@@ -2505,11 +2505,11 @@
2505 cid = db_lget_int("checkout", 0);
2506 if( cid == 0 ){
2507 fossil_fatal("Not in a checkout");
2508 }
2509 if( iLimit<=0 ) iLimit = 1000000000;
2510 compute_direct_ancestors(cid, 1000000);
2511 mid = db_int(0, "SELECT mlink.mid FROM mlink, ancestor "
2512 " WHERE mlink.fid=%d AND mlink.fnid=%d AND mlink.mid=ancestor.rid"
2513 " ORDER BY ancestor.generation ASC LIMIT 1",
2514 fid, fnid);
2515 if( mid==0 ){
2516
--- src/diff.c
+++ src/diff.c
@@ -2299,11 +2299,11 @@
2299 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
2300 fossil_redirect_home();
2301 }
2302
2303 /* compute the annotation */
2304 compute_direct_ancestors(mid);
2305 annotate_file(&ann, fnid, mid, iLimit, annFlags);
2306 zCI = ann.aVers[0].zMUuid;
2307
2308 /* generate the web page */
2309 style_header("Annotation For %h", zFilename);
@@ -2505,11 +2505,11 @@
2505 cid = db_lget_int("checkout", 0);
2506 if( cid == 0 ){
2507 fossil_fatal("Not in a checkout");
2508 }
2509 if( iLimit<=0 ) iLimit = 1000000000;
2510 compute_direct_ancestors(cid);
2511 mid = db_int(0, "SELECT mlink.mid FROM mlink, ancestor "
2512 " WHERE mlink.fid=%d AND mlink.fnid=%d AND mlink.mid=ancestor.rid"
2513 " ORDER BY ancestor.generation ASC LIMIT 1",
2514 fid, fnid);
2515 if( mid==0 ){
2516

Keyboard Shortcuts

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