Fossil SCM
Faster resolution of common symbolic tags such as "trunk".
Commit
fdeebddea7abf6addf1640da01804f230e9a10c2b081b0aafdcac1642d0412ba
Parent
a28778e1d8feee3…
1 file changed
+56
-22
+56
-22
| --- src/name.c | ||
| +++ src/name.c | ||
| @@ -181,10 +181,53 @@ | ||
| 181 | 181 | ans = compute_youngest_ancestor_in_branch(rid, zBr); |
| 182 | 182 | fossil_free(zBr); |
| 183 | 183 | } |
| 184 | 184 | return ans; |
| 185 | 185 | } |
| 186 | + | |
| 187 | +/* | |
| 188 | +** Find the RID of the most recent object with symbolic tag zTag | |
| 189 | +** and having a type that matches zType. | |
| 190 | +** | |
| 191 | +** Return 0 if there are no matches. | |
| 192 | +** | |
| 193 | +** This is a tricky query to do efficiently. | |
| 194 | +** If the tag is very common (ex: "trunk") then | |
| 195 | +** we want to use the query identified below as Q1 - which searching | |
| 196 | +** the most recent EVENT table entries for the most recent with the tag. | |
| 197 | +** But if the tag is relatively scarce (anything other than "trunk", basically) | |
| 198 | +** then we want to do the indexed search show below as Q2. | |
| 199 | +*/ | |
| 200 | +static int most_recent_event_with_tag(const char *zTag, const char *zType){ | |
| 201 | + return db_int(0, | |
| 202 | + "SELECT objid FROM (" | |
| 203 | + /* Q1: Begin by looking for the tag in the 30 most recent events */ | |
| 204 | + "SELECT objid" | |
| 205 | + " FROM (SELECT * FROM event ORDER BY mtime DESC LIMIT 30) AS ex" | |
| 206 | + " WHERE type GLOB '%q'" | |
| 207 | + " AND EXISTS(SELECT 1 FROM tagxref, tag" | |
| 208 | + " WHERE tag.tagname='sym-%q'" | |
| 209 | + " AND tagxref.tagid=tag.tagid" | |
| 210 | + " AND tagxref.tagtype>0" | |
| 211 | + " AND tagxref.rid=ex.objid)" | |
| 212 | + " ORDER BY mtime DESC LIMIT 1" | |
| 213 | + ") UNION ALL SELECT * FROM (" | |
| 214 | + /* Q2: If the tag is not found in the 30 most recent events, then using | |
| 215 | + ** the tagxref table to index for the tag */ | |
| 216 | + "SELECT event.objid" | |
| 217 | + " FROM tag, tagxref, event" | |
| 218 | + " WHERE tag.tagname='sym-%q'" | |
| 219 | + " AND tagxref.tagid=tag.tagid" | |
| 220 | + " AND tagxref.tagtype>0" | |
| 221 | + " AND event.objid=tagxref.rid" | |
| 222 | + " AND event.type GLOB '%q'" | |
| 223 | + " ORDER BY event.mtime DESC LIMIT 1" | |
| 224 | + ") LIMIT 1;", | |
| 225 | + zType, zTag, zTag, zType | |
| 226 | + ); | |
| 227 | +} | |
| 228 | + | |
| 186 | 229 | |
| 187 | 230 | /* |
| 188 | 231 | ** Convert a symbolic name into a RID. Acceptable forms: |
| 189 | 232 | ** |
| 190 | 233 | ** * artifact hash (optionally enclosed in [...]) |
| @@ -225,11 +268,10 @@ | ||
| 225 | 268 | int i; |
| 226 | 269 | int startOfBranch = 0; |
| 227 | 270 | const char *zXTag; /* zTag with optional [...] removed */ |
| 228 | 271 | int nXTag; /* Size of zXTag */ |
| 229 | 272 | const char *zDate; /* Expanded date-time string */ |
| 230 | - const char *zTagPrefix = "sym"; | |
| 231 | 273 | |
| 232 | 274 | if( zType==0 || zType[0]==0 ){ |
| 233 | 275 | zType = "*"; |
| 234 | 276 | }else if( zType[0]=='b' ){ |
| 235 | 277 | zType = "ci"; |
| @@ -301,19 +343,11 @@ | ||
| 301 | 343 | return rid; |
| 302 | 344 | } |
| 303 | 345 | |
| 304 | 346 | /* "tag:" + symbolic-name */ |
| 305 | 347 | if( memcmp(zTag, "tag:", 4)==0 ){ |
| 306 | - rid = db_int(0, | |
| 307 | - "SELECT event.objid, max(event.mtime)" | |
| 308 | - " FROM tag, tagxref, event" | |
| 309 | - " WHERE tag.tagname='sym-%q' " | |
| 310 | - " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 " | |
| 311 | - " AND event.objid=tagxref.rid " | |
| 312 | - " AND event.type GLOB '%q'", | |
| 313 | - &zTag[4], zType | |
| 314 | - ); | |
| 348 | + rid = most_recent_event_with_tag(&zTag[4], zType); | |
| 315 | 349 | if( startOfBranch ) rid = start_of_branch(rid,1); |
| 316 | 350 | return rid; |
| 317 | 351 | } |
| 318 | 352 | |
| 319 | 353 | /* root:BR -> The origin of the branch named BR */ |
| @@ -396,22 +430,22 @@ | ||
| 396 | 430 | db_finalize(&q); |
| 397 | 431 | if( rid ) return rid; |
| 398 | 432 | } |
| 399 | 433 | |
| 400 | 434 | if( zType[0]=='w' ){ |
| 401 | - zTagPrefix = "wiki"; | |
| 402 | - } | |
| 403 | - /* Symbolic name */ | |
| 404 | - rid = db_int(0, | |
| 405 | - "SELECT event.objid, max(event.mtime)" | |
| 406 | - " FROM tag, tagxref, event" | |
| 407 | - " WHERE tag.tagname='%q-%q' " | |
| 408 | - " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 " | |
| 409 | - " AND event.objid=tagxref.rid " | |
| 410 | - " AND event.type GLOB '%q'", | |
| 411 | - zTagPrefix, zTag, zType | |
| 412 | - ); | |
| 435 | + rid = db_int(0, | |
| 436 | + "SELECT event.objid, max(event.mtime)" | |
| 437 | + " FROM tag, tagxref, event" | |
| 438 | + " WHERE tag.tagname='wiki-%q' " | |
| 439 | + " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 " | |
| 440 | + " AND event.objid=tagxref.rid " | |
| 441 | + " AND event.type GLOB '%q'", | |
| 442 | + zTag, zType | |
| 443 | + ); | |
| 444 | + }else{ | |
| 445 | + rid = most_recent_event_with_tag(zTag, zType); | |
| 446 | + } | |
| 413 | 447 | |
| 414 | 448 | if( rid>0 ){ |
| 415 | 449 | if( startOfBranch ) rid = start_of_branch(rid,1); |
| 416 | 450 | return rid; |
| 417 | 451 | } |
| 418 | 452 |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -181,10 +181,53 @@ | |
| 181 | ans = compute_youngest_ancestor_in_branch(rid, zBr); |
| 182 | fossil_free(zBr); |
| 183 | } |
| 184 | return ans; |
| 185 | } |
| 186 | |
| 187 | /* |
| 188 | ** Convert a symbolic name into a RID. Acceptable forms: |
| 189 | ** |
| 190 | ** * artifact hash (optionally enclosed in [...]) |
| @@ -225,11 +268,10 @@ | |
| 225 | int i; |
| 226 | int startOfBranch = 0; |
| 227 | const char *zXTag; /* zTag with optional [...] removed */ |
| 228 | int nXTag; /* Size of zXTag */ |
| 229 | const char *zDate; /* Expanded date-time string */ |
| 230 | const char *zTagPrefix = "sym"; |
| 231 | |
| 232 | if( zType==0 || zType[0]==0 ){ |
| 233 | zType = "*"; |
| 234 | }else if( zType[0]=='b' ){ |
| 235 | zType = "ci"; |
| @@ -301,19 +343,11 @@ | |
| 301 | return rid; |
| 302 | } |
| 303 | |
| 304 | /* "tag:" + symbolic-name */ |
| 305 | if( memcmp(zTag, "tag:", 4)==0 ){ |
| 306 | rid = db_int(0, |
| 307 | "SELECT event.objid, max(event.mtime)" |
| 308 | " FROM tag, tagxref, event" |
| 309 | " WHERE tag.tagname='sym-%q' " |
| 310 | " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 " |
| 311 | " AND event.objid=tagxref.rid " |
| 312 | " AND event.type GLOB '%q'", |
| 313 | &zTag[4], zType |
| 314 | ); |
| 315 | if( startOfBranch ) rid = start_of_branch(rid,1); |
| 316 | return rid; |
| 317 | } |
| 318 | |
| 319 | /* root:BR -> The origin of the branch named BR */ |
| @@ -396,22 +430,22 @@ | |
| 396 | db_finalize(&q); |
| 397 | if( rid ) return rid; |
| 398 | } |
| 399 | |
| 400 | if( zType[0]=='w' ){ |
| 401 | zTagPrefix = "wiki"; |
| 402 | } |
| 403 | /* Symbolic name */ |
| 404 | rid = db_int(0, |
| 405 | "SELECT event.objid, max(event.mtime)" |
| 406 | " FROM tag, tagxref, event" |
| 407 | " WHERE tag.tagname='%q-%q' " |
| 408 | " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 " |
| 409 | " AND event.objid=tagxref.rid " |
| 410 | " AND event.type GLOB '%q'", |
| 411 | zTagPrefix, zTag, zType |
| 412 | ); |
| 413 | |
| 414 | if( rid>0 ){ |
| 415 | if( startOfBranch ) rid = start_of_branch(rid,1); |
| 416 | return rid; |
| 417 | } |
| 418 |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -181,10 +181,53 @@ | |
| 181 | ans = compute_youngest_ancestor_in_branch(rid, zBr); |
| 182 | fossil_free(zBr); |
| 183 | } |
| 184 | return ans; |
| 185 | } |
| 186 | |
| 187 | /* |
| 188 | ** Find the RID of the most recent object with symbolic tag zTag |
| 189 | ** and having a type that matches zType. |
| 190 | ** |
| 191 | ** Return 0 if there are no matches. |
| 192 | ** |
| 193 | ** This is a tricky query to do efficiently. |
| 194 | ** If the tag is very common (ex: "trunk") then |
| 195 | ** we want to use the query identified below as Q1 - which searching |
| 196 | ** the most recent EVENT table entries for the most recent with the tag. |
| 197 | ** But if the tag is relatively scarce (anything other than "trunk", basically) |
| 198 | ** then we want to do the indexed search show below as Q2. |
| 199 | */ |
| 200 | static int most_recent_event_with_tag(const char *zTag, const char *zType){ |
| 201 | return db_int(0, |
| 202 | "SELECT objid FROM (" |
| 203 | /* Q1: Begin by looking for the tag in the 30 most recent events */ |
| 204 | "SELECT objid" |
| 205 | " FROM (SELECT * FROM event ORDER BY mtime DESC LIMIT 30) AS ex" |
| 206 | " WHERE type GLOB '%q'" |
| 207 | " AND EXISTS(SELECT 1 FROM tagxref, tag" |
| 208 | " WHERE tag.tagname='sym-%q'" |
| 209 | " AND tagxref.tagid=tag.tagid" |
| 210 | " AND tagxref.tagtype>0" |
| 211 | " AND tagxref.rid=ex.objid)" |
| 212 | " ORDER BY mtime DESC LIMIT 1" |
| 213 | ") UNION ALL SELECT * FROM (" |
| 214 | /* Q2: If the tag is not found in the 30 most recent events, then using |
| 215 | ** the tagxref table to index for the tag */ |
| 216 | "SELECT event.objid" |
| 217 | " FROM tag, tagxref, event" |
| 218 | " WHERE tag.tagname='sym-%q'" |
| 219 | " AND tagxref.tagid=tag.tagid" |
| 220 | " AND tagxref.tagtype>0" |
| 221 | " AND event.objid=tagxref.rid" |
| 222 | " AND event.type GLOB '%q'" |
| 223 | " ORDER BY event.mtime DESC LIMIT 1" |
| 224 | ") LIMIT 1;", |
| 225 | zType, zTag, zTag, zType |
| 226 | ); |
| 227 | } |
| 228 | |
| 229 | |
| 230 | /* |
| 231 | ** Convert a symbolic name into a RID. Acceptable forms: |
| 232 | ** |
| 233 | ** * artifact hash (optionally enclosed in [...]) |
| @@ -225,11 +268,10 @@ | |
| 268 | int i; |
| 269 | int startOfBranch = 0; |
| 270 | const char *zXTag; /* zTag with optional [...] removed */ |
| 271 | int nXTag; /* Size of zXTag */ |
| 272 | const char *zDate; /* Expanded date-time string */ |
| 273 | |
| 274 | if( zType==0 || zType[0]==0 ){ |
| 275 | zType = "*"; |
| 276 | }else if( zType[0]=='b' ){ |
| 277 | zType = "ci"; |
| @@ -301,19 +343,11 @@ | |
| 343 | return rid; |
| 344 | } |
| 345 | |
| 346 | /* "tag:" + symbolic-name */ |
| 347 | if( memcmp(zTag, "tag:", 4)==0 ){ |
| 348 | rid = most_recent_event_with_tag(&zTag[4], zType); |
| 349 | if( startOfBranch ) rid = start_of_branch(rid,1); |
| 350 | return rid; |
| 351 | } |
| 352 | |
| 353 | /* root:BR -> The origin of the branch named BR */ |
| @@ -396,22 +430,22 @@ | |
| 430 | db_finalize(&q); |
| 431 | if( rid ) return rid; |
| 432 | } |
| 433 | |
| 434 | if( zType[0]=='w' ){ |
| 435 | rid = db_int(0, |
| 436 | "SELECT event.objid, max(event.mtime)" |
| 437 | " FROM tag, tagxref, event" |
| 438 | " WHERE tag.tagname='wiki-%q' " |
| 439 | " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 " |
| 440 | " AND event.objid=tagxref.rid " |
| 441 | " AND event.type GLOB '%q'", |
| 442 | zTag, zType |
| 443 | ); |
| 444 | }else{ |
| 445 | rid = most_recent_event_with_tag(zTag, zType); |
| 446 | } |
| 447 | |
| 448 | if( rid>0 ){ |
| 449 | if( startOfBranch ) rid = start_of_branch(rid,1); |
| 450 | return rid; |
| 451 | } |
| 452 |