Fossil

Check-in [6809145e]
Login

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

Overview
Comment:More comments on sql statements.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:6809145eb16fb372e2e15f2dbc76b024db4fd095
User & Date: aku 2008-01-19 06:07:49
Context
2008-01-27
20:38
Added comments to the sql commands in the integrity checks. check-in: 727f370c user: aku tags: trunk
2008-01-19
06:07
More comments on sql statements. check-in: 6809145e user: aku tags: trunk
2007-12-08
03:39
More comments on sql statements, slight reordering of some tables and conditions. check-in: f7fe15cd user: aku tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to tools/cvs2fossil/lib/c2f_pcollrev.tcl.

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
	    tid    INTEGER  NOT NULL  PRIMARY KEY,
	    name   TEXT     NOT NULL,
	    plural TEXT     NOT NULL,
	    UNIQUE (name)
	    UNIQUE (plural)
	}
	state run {
	    INSERT INTO symtype VALUES (0,'excluded', 'excluded');
	    INSERT INTO symtype VALUES (1,'tag',      'tags');
	    INSERT INTO symtype VALUES (2,'branch',   'branches');
	    INSERT INTO symtype VALUES (3,'undefined','undefined');
	}

	state extend meta {
	    -- Meta data of revisions. See revision.mid for the
	    -- reference. Many revisions can share meta data. This is
	    -- actually one of the criterions used to sort revisions
	    -- into changesets.
................................................................................
	    --              of X itself.
	}

	# Authors and commit messages are fully global, i.e. per
	# repository.

	state extend author {
	    aid  INTEGER  NOT NULL  PRIMARY KEY  AUTOINCREMENT,
	    name TEXT     NOT NULL  UNIQUE
	}

	state extend cmessage {
	    cid  INTEGER  NOT NULL  PRIMARY KEY  AUTOINCREMENT,
	    text TEXT     NOT NULL  UNIQUE
	}

	project::sym getsymtypes
	file::rev    getopcodes
	return
    }








|
|
|
|







 







|
|



|
|







245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
	    tid    INTEGER  NOT NULL  PRIMARY KEY,
	    name   TEXT     NOT NULL,
	    plural TEXT     NOT NULL,
	    UNIQUE (name)
	    UNIQUE (plural)
	}
	state run {
	    INSERT INTO symtype VALUES (0,'excluded', 'excluded');  -- The ids are the fixed
	    INSERT INTO symtype VALUES (1,'tag',      'tags');      -- pieces, see project::sym,
	    INSERT INTO symtype VALUES (2,'branch',   'branches');  -- getsymtypes and associated
	    INSERT INTO symtype VALUES (3,'undefined','undefined'); -- typevariables.
	}

	state extend meta {
	    -- Meta data of revisions. See revision.mid for the
	    -- reference. Many revisions can share meta data. This is
	    -- actually one of the criterions used to sort revisions
	    -- into changesets.
................................................................................
	    --              of X itself.
	}

	# Authors and commit messages are fully global, i.e. per
	# repository.

	state extend author {
	    aid  INTEGER  NOT NULL  PRIMARY KEY  AUTOINCREMENT, -- Pool of the unique
	    name TEXT     NOT NULL  UNIQUE                      -- author names.
	}

	state extend cmessage {
	    cid  INTEGER  NOT NULL  PRIMARY KEY  AUTOINCREMENT, -- Pool of the unique
	    text TEXT     NOT NULL  UNIQUE                      -- log messages
	}

	project::sym getsymtypes
	file::rev    getopcodes
	return
    }

Changes to tools/cvs2fossil/lib/c2f_pfiltersym.tcl.

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
...
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
...
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
...
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
...
470
471
472
473
474
475
476



477
478
479
480
481
482
483

	array set ntdb {}
	array set link {}

	foreach {id parent transfer} [state run {
	    SELECT R.rid, R.parent, R.dbchild
	    FROM  revision R, symbol S
	    WHERE R.lod = S.sid
	    AND   S.sid IN excludedsymbols
	    AND   R.isdefault
	}] {
	    set ntdb($id) $parent
	    if {$transfer eq ""} continue
	    set link($id) $transfer
	}

	foreach joint [array names link] {
................................................................................
		FROM   file F, project P
		WHERE  F.pid = P.pid
	}] { set fpn($id) [list $fn $pn] }

	set tagstoadjust [state run {
	    SELECT T.tid, T.fid, T.lod, P.pid, S.name, R.rev, R.rid
	    FROM tag T, preferedparent P, symbol S, revision R
	    WHERE T.sid = P.sid
	    AND   T.lod != P.pid
	    AND   P.pid = S.sid
	    AND   S.name != ':trunk:'
	    AND   T.rev = R.rid
	}]

	set branchestoadjust [state run {
	    SELECT B.bid, B.fid, B.lod, B.pos, P.pid, S.name, NULL, NULL
	    FROM branch B, preferedparent P, symbol S
	    WHERE B.sid = P.sid
	    AND   B.lod != P.pid
	    AND   P.pid = S.sid
	    AND   S.name != ':trunk:'
	    AND   B.root IS NULL -- Accept free-floating branch
	    UNION
	    SELECT B.bid, B.fid, B.lod, B.pos, P.pid, S.name, R.rev, R.rid
	    FROM branch B, preferedparent P, symbol S, revision R
	    WHERE B.sid = P.sid
	    AND   B.lod != P.pid
	    AND   P.pid = S.sid
	    AND   S.name != ':trunk:'
	    AND   B.root = R.rid
	}]

	set tmax [expr {[llength $tagstoadjust] / 7}]
	set bmax [expr {[llength $branchestoadjust] / 8}]

	log write 4 filtersym "Reparenting at most [nsp $tmax tag]"
	log write 4 filtersym "Reparenting at most [nsp $bmax branch branches]"
................................................................................
	set mxs [format $fmt $tmax]

	set n 0
	foreach {id fid lod pid preferedname revnr rid} $tagstoadjust {
	    # BOTTLE-NECK ...
	    #
	    # The check if the candidate (pid) is truly viable is
	    # based finding the branch as possible parent, and done
	    # now instead of as part of the already complex join.
	    #
	    # ... AND P.pid IN (SELECT B.sid
	    #                   FROM branch B
	    #                   WHERE B.root = R.rid)

	    if {![state one {
		SELECT COUNT(*)
		FROM branch B
		WHERE  B.sid  = $pid
		AND    B.root = $rid
	    }]} {
		incr tmax -1
		set  mxs [format $fmt $tmax]
		continue
	    }

	    #
................................................................................
	    # branch, whose original root was removed as a unnecessary
	    # dead revision (See 'file::RemoveIrrelevantDeletions').
	    # Such a branch can be regrafted without trouble and there
	    # is no need to look for the new parent in its
	    # non-existent root.

	    if {($rid ne "") && ![state one {
		SELECT COUNT(*)
		FROM branch B
		WHERE  B.sid  = $pid
		AND    B.root = $rid
		AND    B.pos  > $pos
	    }]} {
		incr bmax -1
		set  mxs [format $fmt $bmax]
		continue
	    }

	    #
................................................................................

    proc RefineSymbols {} {
	# Tags and branches are marked as normal/noop based on the op
	# of their revision.

	log write 3 filtersym "Refine symbols (no-op or not?)"




	log write 4 filtersym "    Regular tags"
	state run {
	    INSERT INTO noop
	    SELECT T.tid, 0
	    FROM tag T, revision R
	    WHERE T.rev  = R.rid
	    AND   R.op  != 0 -- 0 == nothing







|
|
|







 







|
|
|
|
|





|
|
|
|
|
|


|
|
|
|
|







 







|







|

|
|







 







|

|
|
|







 







>
>
>







147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
...
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
...
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
...
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
...
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486

	array set ntdb {}
	array set link {}

	foreach {id parent transfer} [state run {
	    SELECT R.rid, R.parent, R.dbchild
	    FROM  revision R, symbol S
	    WHERE R.lod = S.sid            -- Get symbol of line-of-development of all revisions
	    AND   S.sid IN excludedsymbols -- Restrict to the excluded symbols
	    AND   R.isdefault              -- Restrict to NTDB revisions
	}] {
	    set ntdb($id) $parent
	    if {$transfer eq ""} continue
	    set link($id) $transfer
	}

	foreach joint [array names link] {
................................................................................
		FROM   file F, project P
		WHERE  F.pid = P.pid
	}] { set fpn($id) [list $fn $pn] }

	set tagstoadjust [state run {
	    SELECT T.tid, T.fid, T.lod, P.pid, S.name, R.rev, R.rid
	    FROM tag T, preferedparent P, symbol S, revision R
	    WHERE T.sid = P.sid        -- For all tags, get left-hand of prefered parent via symbol
	    AND   T.lod != P.pid       -- Restrict to tags whose LOD is not their prefered parent
	    AND   P.pid = S.sid        -- Get symbol of prefered parent
	    AND   S.name != ':trunk:'  -- Exclude trunk parentage
	    AND   T.rev = R.rid        -- Get revision the tag is attached to.
	}]

	set branchestoadjust [state run {
	    SELECT B.bid, B.fid, B.lod, B.pos, P.pid, S.name, NULL, NULL
	    FROM branch B, preferedparent P, symbol S
	    WHERE B.sid = P.sid        -- For all branches, get left-hand of prefered parent via symbol
	    AND   B.lod != P.pid       -- Restrict to branches whose LOD is not their prefered parent
	    AND   P.pid = S.sid        -- Get symbol of prefered parent
	    AND   S.name != ':trunk:'  -- Exclude trunk parentage
	    AND   B.root IS NULL       -- Accept free-floating branch
    UNION
	    SELECT B.bid, B.fid, B.lod, B.pos, P.pid, S.name, R.rev, R.rid
	    FROM branch B, preferedparent P, symbol S, revision R
	    WHERE B.sid = P.sid        -- For all branches, get left-hand of prefered parent via symbol
	    AND   B.lod != P.pid       -- Restrict to branches whose LOD is not their prefered parent
	    AND   P.pid = S.sid	       -- Get symbol of prefered parent
	    AND   S.name != ':trunk:'  -- Exclude trunk parentage
	    AND   B.root = R.rid       -- Get root revision of the branch
	}]

	set tmax [expr {[llength $tagstoadjust] / 7}]
	set bmax [expr {[llength $branchestoadjust] / 8}]

	log write 4 filtersym "Reparenting at most [nsp $tmax tag]"
	log write 4 filtersym "Reparenting at most [nsp $bmax branch branches]"
................................................................................
	set mxs [format $fmt $tmax]

	set n 0
	foreach {id fid lod pid preferedname revnr rid} $tagstoadjust {
	    # BOTTLE-NECK ...
	    #
	    # The check if the candidate (pid) is truly viable is
	    # based on finding the branch as possible parent, and done
	    # now instead of as part of the already complex join.
	    #
	    # ... AND P.pid IN (SELECT B.sid
	    #                   FROM branch B
	    #                   WHERE B.root = R.rid)

	    if {![state one {
		SELECT COUNT(*)       -- Count <=> Check existence.
		FROM branch B
		WHERE  B.sid  = $pid  -- Restrict to branch for that symbol
		AND    B.root = $rid  -- attached to that revision
	    }]} {
		incr tmax -1
		set  mxs [format $fmt $tmax]
		continue
	    }

	    #
................................................................................
	    # branch, whose original root was removed as a unnecessary
	    # dead revision (See 'file::RemoveIrrelevantDeletions').
	    # Such a branch can be regrafted without trouble and there
	    # is no need to look for the new parent in its
	    # non-existent root.

	    if {($rid ne "") && ![state one {
		SELECT COUNT(*)       -- Count <=> Check existence.
		FROM branch B
		WHERE  B.sid  = $pid  -- Look for branch by symbol
		AND    B.root = $rid  -- Spawned by the given revision
		AND    B.pos  > $pos  -- And defined before branch to mutate
	    }]} {
		incr bmax -1
		set  mxs [format $fmt $bmax]
		continue
	    }

	    #
................................................................................

    proc RefineSymbols {} {
	# Tags and branches are marked as normal/noop based on the op
	# of their revision.

	log write 3 filtersym "Refine symbols (no-op or not?)"

	# Note: The noop information is not used anywhere. Consider
	# disabling this code, and removing the data from the state.

	log write 4 filtersym "    Regular tags"
	state run {
	    INSERT INTO noop
	    SELECT T.tid, 0
	    FROM tag T, revision R
	    WHERE T.rev  = R.rid
	    AND   R.op  != 0 -- 0 == nothing

Changes to tools/cvs2fossil/lib/c2f_prev.tcl.

740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
...
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
...
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
...
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
...
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
....
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
....
1046
1047
1048
1049
1050
1051
1052

1053
1054
1055
1056
1057
1058
1059
1060

1061
1062
1063
1064
1065
1066
1067
1068

1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
....
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
....
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
....
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
....
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
....
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
....
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
    # number), for high verbosity log output.
    # TODO: Replace with call to itemstr (list rev $id)

    proc PD {id} {
	foreach {p f r} [state run {
		SELECT P.name , F.name, R.rev
		FROM revision R, file F, project P
		WHERE R.rid = $id
		AND   F.fid = R.fid
		AND   P.pid = F.pid
	}] break
	return "'$p : $f/$r'"
    }

    # Printing one or more ranges, formatted, and only their border to
    # keep the strings short.

................................................................................
    typemethod istag      {} { return 0 }
    typemethod isbranch   {} { return 0 }

    typemethod str {revision} {
	struct::list assign [state run {
	    SELECT R.rev, F.name, P.name
	    FROM   revision R, file F, project P
	    WHERE  R.rid = $revision
	    AND    F.fid = R.fid
	    AND    P.pid = F.pid
	}] revnr fname pname
	return "$pname/${revnr}::$fname"
    }

    # result = list (mintime, maxtime)
    typemethod timerange {items} {
	set theset ('[join $items {','}]')
	return [state run [subst -nocommands -nobackslashes {
	    SELECT MIN(R.date), MAX(R.date)
	    FROM revision R
	    WHERE R.rid IN $theset
	}]]
    }

    # var(dv) = dict (revision -> list (revision))
    typemethod internalsuccessors {dv revisions} {
	upvar 1 $dv dependencies
	set theset ('[join $revisions {','}]')
................................................................................
	# restricts the successors we look for to the same set of
	# revisions we start from. Sensible as we are looking for
	# changeset internal dependencies.

	array set dep {}

	foreach {rid child} [state run [subst -nocommands -nobackslashes {
   -- (1) Primary child
	    SELECT R.rid, R.child
	    FROM   revision R
	    WHERE  R.rid   IN $theset     -- Restrict to revisions of interest
	    AND    R.child IS NOT NULL    -- Has primary child
	    AND    R.child IN $theset     -- Which is also of interest
    UNION
    -- (2) Secondary (branch) children
................................................................................
	}
	return
    }

    # result = 4-list (itemtype itemid nextitemtype nextitemid ...)
    typemethod loops {revisions} {
	# Note: Tags and branches cannot cause the loop. Their id's,
	# bein of a fundamentally different type than the revisions
	# coming in cannot be in the set.

	set theset ('[join $revisions {','}]')
	return [state run [subst -nocommands -nobackslashes {
	    -- (1) Primary child
	    SELECT R.rid, R.child
	    FROM   revision R
................................................................................
	#     the trunk, then the primary child of the trunk root (the
	#     '1.2' revision) is a successor, if it exists.

	# Note that the branches spawned from the revisions, and the
	# tags associated with them are successors as well.

	foreach {rid child} [state run [subst -nocommands -nobackslashes {
   -- (1) Primary child
	    SELECT R.rid, R.child
	    FROM   revision R
	    WHERE  R.rid   IN $theset     -- Restrict to revisions of interest
	    AND    R.child IS NOT NULL    -- Has primary child
    UNION
    -- (2) Secondary (branch) children
	    SELECT R.rid, B.brid
................................................................................
	    # Consider moving this to the integrity module.
	    integrity assert {$rid != $child} {Revision $rid depends on itself.}
	    lappend dependencies([list rev $rid]) [list rev $child]
	}
	foreach {rid child} [state run [subst -nocommands -nobackslashes {
	    SELECT R.rid, T.tid
	    FROM   revision R, tag T
	    WHERE  R.rid IN $theset
	    AND    T.rev = R.rid
	}]] {
	    lappend dependencies([list rev $rid]) [list sym::tag $child]
	}
	foreach {rid child} [state run [subst -nocommands -nobackslashes {
	    SELECT R.rid, B.bid
	    FROM   revision R, branch B
	    WHERE  R.rid IN $theset
	    AND    B.root = R.rid
	}]] {
	    lappend dependencies([list rev $rid]) [list sym::branch $child]
	}
	return
    }

    # result = list (changeset-id)
................................................................................
        # data directly to the associated changesets. I.e. instead
        # millions of dependency pairs (in extreme cases (Example: Tcl
        # CVS)) we return a very short and much more manageable list
        # of changesets.

	set theset ('[join $revisions {','}]')
	return [state run [subst -nocommands -nobackslashes {

	    SELECT C.cid
	    FROM   revision R, csitem CI, changeset C
	    WHERE  R.rid   IN $theset     -- Restrict to revisions of interest
	    AND    R.child IS NOT NULL    -- Has primary child
            AND    CI.iid = R.child
            AND    C.cid = CI.cid
            AND    C.type = 0
    UNION

	    SELECT C.cid
	    FROM   revision R, revisionbranchchildren B, csitem CI, changeset C
	    WHERE  R.rid   IN $theset     -- Restrict to revisions of interest
	    AND    R.rid = B.rid          -- Select subset of branch children
            AND    CI.iid = B.brid
            AND    C.cid = CI.cid
            AND    C.type = 0
    UNION

	    SELECT C.cid
	    FROM   revision R, revision RA, csitem CI, changeset C
	    WHERE  R.rid   IN $theset      -- Restrict to revisions of interest
	    AND    R.isdefault             -- Restrict to NTDB
	    AND    R.dbchild IS NOT NULL   -- and last NTDB belonging to trunk
	    AND    RA.rid = R.dbchild      -- Go directly to trunk root
	    AND    RA.child IS NOT NULL    -- Has primary child.
            AND    CI.iid = RA.child
            AND    C.cid = CI.cid
            AND    C.type = 0
    UNION
	    SELECT C.cid
	    FROM   revision R, tag T, csitem CI, changeset C
	    WHERE  R.rid in $theset
	    AND    T.rev = R.rid
            AND    CI.iid = T.tid
            AND    C.cid = CI.cid
            AND    C.type = 1
    UNION
	    SELECT C.cid
	    FROM   revision R, branch B, csitem CI, changeset C
	    WHERE  R.rid in $theset
	    AND    B.root = R.rid
            AND    CI.iid = B.bid
            AND    C.cid = CI.cid
            AND    C.type = 2
	}]]
    }
}

# # ## ### ##### ######## ############# #####################
## Helper singleton. Commands for tag symbol changesets.

................................................................................
    typemethod istag      {} { return 1 }
    typemethod isbranch   {} { return 0 }

    typemethod str {tag} {
	struct::list assign [state run {
	    SELECT S.name, F.name, P.name
	    FROM   tag T, symbol S, file F, project P
	    WHERE  T.tid = $tag
	    AND    F.fid = T.fid
	    AND    P.pid = F.pid
	    AND    S.sid = T.sid
	}] sname fname pname
	return "$pname/T'${sname}'::$fname"
    }

    # result = list (mintime, maxtime)
    typemethod timerange {tags} {
	# The range is defined as the range of the revisions the tags
	# are attached to.

	set theset ('[join $tags {','}]')
	return [state run [subst -nocommands -nobackslashes {
	    SELECT MIN(R.date), MAX(R.date)
	    FROM   tag T, revision R
	    WHERE  T.tid IN $theset
            AND    R.rid = T.rev
	}]]
    }

    # var(dv) = dict (item -> list (item)), item  = list (type id)
    typemethod successors {dv tags} {
	# Tags have no successors.
	return
................................................................................
    typemethod istag      {} { return 0 }
    typemethod isbranch   {} { return 1 }

    typemethod str {branch} {
	struct::list assign [state run {
	    SELECT S.name, F.name, P.name
	    FROM   branch B, symbol S, file F, project P
	    WHERE  B.bid = $branch
	    AND    F.fid = B.fid
	    AND    P.pid = F.pid
	    AND    S.sid = B.sid
	}] sname fname pname
	return "$pname/B'${sname}'::$fname"
    }

    # result = list (mintime, maxtime)
    typemethod timerange {branches} {
	# The range of a branch is defined as the range of the
................................................................................
	# longer. By using 0 we put them in front of everything else,
	# as they logically are.

	set theset ('[join $branches {','}]')
	return [state run [subst -nocommands -nobackslashes {
	    SELECT IFNULL(MIN(R.date),0), IFNULL(MAX(R.date),0)
	    FROM  branch B, revision R
	    WHERE B.bid IN $theset
            AND   R.rid = B.root
	}]]
    }

    # result = 4-list (itemtype itemid nextitemtype nextitemid ...)
    typemethod loops {branches} {
	# Note: Revisions and tags cannot cause the loop. Being of a
	# fundamentally different type they cannot be in the incoming
	# set of ids.

	set theset ('[join $branches {','}]')
	return [state run [subst -nocommands -nobackslashes {
	    SELECT B.bid, BX.bid
	    FROM   branch B, preferedparent P, branch BX
	    WHERE  B.bid IN $theset
	    AND    B.sid = P.pid
	    AND    BX.sid = P.sid
	    AND    BX.bid IN $theset
	}]]
    }

    # var(dv) = dict (item -> list (item)), item  = list (type id)
    typemethod successors {dv branches} {
	upvar 1 $dv dependencies
	# The first revision committed on a branch, and all branches
................................................................................
	# and tags which have it as their prefered parent are the
	# successors of a branch.

	set theset ('[join $branches {','}]')
	foreach {bid child} [state run [subst -nocommands -nobackslashes {
	    SELECT B.bid, R.rid
	    FROM   branch B, revision R
	    WHERE  B.bid IN $theset
	    AND    B.first = R.rid
	}]] {
	    lappend dependencies([list sym::branch $bid]) [list rev $child]
	}
	foreach {bid child} [state run [subst -nocommands -nobackslashes {
	    SELECT B.bid, BX.bid
	    FROM   branch B, preferedparent P, branch BX
	    WHERE  B.bid IN $theset
	    AND    B.sid = P.pid
	    AND    BX.sid = P.sid
	}]] {
	    lappend dependencies([list sym::branch $bid]) [list sym::branch $child]
	}
	foreach {bid child} [state run [subst -nocommands -nobackslashes {
	    SELECT B.bid, T.tid
	    FROM   branch B, preferedparent P, tag T
	    WHERE  B.bid IN $theset
	    AND    B.sid = P.pid
	    AND    T.sid = P.sid
	}]] {
	    lappend dependencies([list sym::branch $bid]) [list sym::tag $child]
	}
	return
    }

    # result = list (changeset-id)
................................................................................
        # CVS)) we return a very short and much more manageable list
        # of changesets.

	set theset ('[join $branches {','}]')
        return [state run [subst -nocommands -nobackslashes {
	    SELECT C.cid
	    FROM   branch B, revision R, csitem CI, changeset C
	    WHERE  B.bid IN $theset
	    AND    B.first = R.rid
            AND    CI.iid = R.rid
            AND    C.cid = CI.cid
            AND    C.type = 0
    UNION
	    SELECT C.cid
	    FROM   branch B, preferedparent P, branch BX, csitem CI, changeset C
	    WHERE  B.bid IN $theset
	    AND    B.sid = P.pid
	    AND    BX.sid = P.sid
            AND    CI.iid = BX.bid
            AND    C.cid = CI.cid
            AND    C.type = 2
    UNION
	    SELECT C.cid
	    FROM   branch B, preferedparent P, tag T, csitem CI, changeset C
	    WHERE  B.bid IN $theset
	    AND    B.sid = P.pid
	    AND    T.sid = P.sid
            AND    CI.iid = T.tid
            AND    C.cid = CI.cid
            AND    C.type = 1
	}]]
	return
    }

    typemethod limits {branches} {
	# Notes. This method exists only for branches. It is needed to
	# get detailed information about a backward branch. It does
................................................................................

	set theset ('[join $branches {','}]')

	set maxp [state run [subst -nocommands -nobackslashes {
	    -- maximal predecessor position per branch
	    SELECT B.bid, MAX (CO.pos)
	    FROM   branch B, revision R, csitem CI, changeset C, csorder CO
	    WHERE  B.bid IN $theset
	    AND    B.root = R.rid
	    AND    CI.iid = R.rid
	    AND    C.cid = CI.cid
	    AND    C.type = 0
	    AND    CO.cid = C.cid
	    GROUP BY B.bid
	}]]

	set mins [state run [subst -nocommands -nobackslashes {
	    -- minimal successor position per branch
	    SELECT B.bid, MIN (CO.pos)
	    FROM   branch B, revision R, csitem CI, changeset C, csorder CO
	    WHERE  B.bid IN $theset
	    AND    B.first = R.rid
	    AND    CI.iid = R.rid
	    AND    C.cid = CI.cid
	    AND    C.type = 0
	    AND    CO.cid = C.cid
	    GROUP BY B.bid
	}]]

        return [list $maxp $mins]
    }

    # # ## ### ##### ######## #############







|
|
|







 







|
|
|










|







 







|







 







|







 







|







 







|
|






|
|







 







>




|
|
|

>




|
|
|

>







|
|
|



|
|
|
|
|



|
|
|
|
|







 







|
|
|
|













|
|







 







|
|
|
|







 







|
|













|
|
|
|







 







|
|






|
|
|






|
|
|







 







|
|
|
|
|



|
|
|
|
|
|



|
|
|
|
|
|







 







|
|
|
|
|
|







|
|
|
|
|
|







740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
...
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
...
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
...
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
...
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
....
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
....
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
....
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
....
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
....
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
....
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
....
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
....
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
    # number), for high verbosity log output.
    # TODO: Replace with call to itemstr (list rev $id)

    proc PD {id} {
	foreach {p f r} [state run {
		SELECT P.name , F.name, R.rev
		FROM revision R, file F, project P
		WHERE R.rid = $id    -- Find specified file revision
		AND   F.fid = R.fid  -- Get file of the revision
		AND   P.pid = F.pid  -- Get project of the file.
	}] break
	return "'$p : $f/$r'"
    }

    # Printing one or more ranges, formatted, and only their border to
    # keep the strings short.

................................................................................
    typemethod istag      {} { return 0 }
    typemethod isbranch   {} { return 0 }

    typemethod str {revision} {
	struct::list assign [state run {
	    SELECT R.rev, F.name, P.name
	    FROM   revision R, file F, project P
	    WHERE  R.rid = $revision -- Find specified file revision
	    AND    F.fid = R.fid     -- Get file of the revision
	    AND    P.pid = F.pid     -- Get project of the file.
	}] revnr fname pname
	return "$pname/${revnr}::$fname"
    }

    # result = list (mintime, maxtime)
    typemethod timerange {items} {
	set theset ('[join $items {','}]')
	return [state run [subst -nocommands -nobackslashes {
	    SELECT MIN(R.date), MAX(R.date)
	    FROM revision R
	    WHERE R.rid IN $theset -- Restrict to revisions of interest
	}]]
    }

    # var(dv) = dict (revision -> list (revision))
    typemethod internalsuccessors {dv revisions} {
	upvar 1 $dv dependencies
	set theset ('[join $revisions {','}]')
................................................................................
	# restricts the successors we look for to the same set of
	# revisions we start from. Sensible as we are looking for
	# changeset internal dependencies.

	array set dep {}

	foreach {rid child} [state run [subst -nocommands -nobackslashes {
    -- (1) Primary child
	    SELECT R.rid, R.child
	    FROM   revision R
	    WHERE  R.rid   IN $theset     -- Restrict to revisions of interest
	    AND    R.child IS NOT NULL    -- Has primary child
	    AND    R.child IN $theset     -- Which is also of interest
    UNION
    -- (2) Secondary (branch) children
................................................................................
	}
	return
    }

    # result = 4-list (itemtype itemid nextitemtype nextitemid ...)
    typemethod loops {revisions} {
	# Note: Tags and branches cannot cause the loop. Their id's,
	# being of a fundamentally different type than the revisions
	# coming in cannot be in the set.

	set theset ('[join $revisions {','}]')
	return [state run [subst -nocommands -nobackslashes {
	    -- (1) Primary child
	    SELECT R.rid, R.child
	    FROM   revision R
................................................................................
	#     the trunk, then the primary child of the trunk root (the
	#     '1.2' revision) is a successor, if it exists.

	# Note that the branches spawned from the revisions, and the
	# tags associated with them are successors as well.

	foreach {rid child} [state run [subst -nocommands -nobackslashes {
    -- (1) Primary child
	    SELECT R.rid, R.child
	    FROM   revision R
	    WHERE  R.rid   IN $theset     -- Restrict to revisions of interest
	    AND    R.child IS NOT NULL    -- Has primary child
    UNION
    -- (2) Secondary (branch) children
	    SELECT R.rid, B.brid
................................................................................
	    # Consider moving this to the integrity module.
	    integrity assert {$rid != $child} {Revision $rid depends on itself.}
	    lappend dependencies([list rev $rid]) [list rev $child]
	}
	foreach {rid child} [state run [subst -nocommands -nobackslashes {
	    SELECT R.rid, T.tid
	    FROM   revision R, tag T
	    WHERE  R.rid IN $theset       -- Restrict to revisions of interest
	    AND    T.rev = R.rid          -- Select tags attached to them
	}]] {
	    lappend dependencies([list rev $rid]) [list sym::tag $child]
	}
	foreach {rid child} [state run [subst -nocommands -nobackslashes {
	    SELECT R.rid, B.bid
	    FROM   revision R, branch B
	    WHERE  R.rid IN $theset       -- Restrict to revisions of interest
	    AND    B.root = R.rid         -- Select branches attached to them
	}]] {
	    lappend dependencies([list rev $rid]) [list sym::branch $child]
	}
	return
    }

    # result = list (changeset-id)
................................................................................
        # data directly to the associated changesets. I.e. instead
        # millions of dependency pairs (in extreme cases (Example: Tcl
        # CVS)) we return a very short and much more manageable list
        # of changesets.

	set theset ('[join $revisions {','}]')
	return [state run [subst -nocommands -nobackslashes {
    -- (1) Primary child
	    SELECT C.cid
	    FROM   revision R, csitem CI, changeset C
	    WHERE  R.rid   IN $theset     -- Restrict to revisions of interest
	    AND    R.child IS NOT NULL    -- Has primary child
            AND    CI.iid = R.child       -- Select all changesets
            AND    C.cid = CI.cid         -- containing the primary child
            AND    C.type = 0             -- which are revision changesets
    UNION
    -- (2) Secondary (branch) children
	    SELECT C.cid
	    FROM   revision R, revisionbranchchildren B, csitem CI, changeset C
	    WHERE  R.rid   IN $theset     -- Restrict to revisions of interest
	    AND    R.rid = B.rid          -- Select subset of branch children
            AND    CI.iid = B.brid        -- Select all changesets
            AND    C.cid = CI.cid	  -- containing the branch
            AND    C.type = 0		  -- which are revision changesets
    UNION
    -- (4) Child of trunk root successor of last NTDB on trunk.
	    SELECT C.cid
	    FROM   revision R, revision RA, csitem CI, changeset C
	    WHERE  R.rid   IN $theset      -- Restrict to revisions of interest
	    AND    R.isdefault             -- Restrict to NTDB
	    AND    R.dbchild IS NOT NULL   -- and last NTDB belonging to trunk
	    AND    RA.rid = R.dbchild      -- Go directly to trunk root
	    AND    RA.child IS NOT NULL    -- Has primary child.
            AND    CI.iid = RA.child       -- Select all changesets
            AND    C.cid = CI.cid	   -- containing the primary child
            AND    C.type = 0		   -- which are revision changesets
    UNION
	    SELECT C.cid
	    FROM   revision R, tag T, csitem CI, changeset C
	    WHERE  R.rid in $theset        -- Restrict to revisions of interest
	    AND    T.rev = R.rid	   -- Select tags attached to them
            AND    CI.iid = T.tid          -- Select all changesets
            AND    C.cid = CI.cid	   -- containing the tags
            AND    C.type = 1		   -- which are tag changesets
    UNION
	    SELECT C.cid
	    FROM   revision R, branch B, csitem CI, changeset C
	    WHERE  R.rid in $theset        -- Restrict to revisions of interest
	    AND    B.root = R.rid	   -- Select branches attached to them
            AND    CI.iid = B.bid          -- Select all changesets
            AND    C.cid = CI.cid	   -- containing the branches
            AND    C.type = 2		   -- which are branch changesets
	}]]
    }
}

# # ## ### ##### ######## ############# #####################
## Helper singleton. Commands for tag symbol changesets.

................................................................................
    typemethod istag      {} { return 1 }
    typemethod isbranch   {} { return 0 }

    typemethod str {tag} {
	struct::list assign [state run {
	    SELECT S.name, F.name, P.name
	    FROM   tag T, symbol S, file F, project P
	    WHERE  T.tid = $tag   -- Find specified tag
	    AND    F.fid = T.fid  -- Get file of tag
	    AND    P.pid = F.pid  -- Get project of file
	    AND    S.sid = T.sid  -- Get symbol of tag
	}] sname fname pname
	return "$pname/T'${sname}'::$fname"
    }

    # result = list (mintime, maxtime)
    typemethod timerange {tags} {
	# The range is defined as the range of the revisions the tags
	# are attached to.

	set theset ('[join $tags {','}]')
	return [state run [subst -nocommands -nobackslashes {
	    SELECT MIN(R.date), MAX(R.date)
	    FROM   tag T, revision R
	    WHERE  T.tid IN $theset  -- Restrict to tags of interest
            AND    R.rid = T.rev     -- Select tag parent revisions
	}]]
    }

    # var(dv) = dict (item -> list (item)), item  = list (type id)
    typemethod successors {dv tags} {
	# Tags have no successors.
	return
................................................................................
    typemethod istag      {} { return 0 }
    typemethod isbranch   {} { return 1 }

    typemethod str {branch} {
	struct::list assign [state run {
	    SELECT S.name, F.name, P.name
	    FROM   branch B, symbol S, file F, project P
	    WHERE  B.bid = $branch  -- Find specified branch
	    AND    F.fid = B.fid    -- Get file of branch
	    AND    P.pid = F.pid    -- Get project of file
	    AND    S.sid = B.sid    -- Get symbol of branch
	}] sname fname pname
	return "$pname/B'${sname}'::$fname"
    }

    # result = list (mintime, maxtime)
    typemethod timerange {branches} {
	# The range of a branch is defined as the range of the
................................................................................
	# longer. By using 0 we put them in front of everything else,
	# as they logically are.

	set theset ('[join $branches {','}]')
	return [state run [subst -nocommands -nobackslashes {
	    SELECT IFNULL(MIN(R.date),0), IFNULL(MAX(R.date),0)
	    FROM  branch B, revision R
	    WHERE B.bid IN $theset   -- Restrict to branches of interest
            AND   R.rid = B.root     -- Select branch parent revisions
	}]]
    }

    # result = 4-list (itemtype itemid nextitemtype nextitemid ...)
    typemethod loops {branches} {
	# Note: Revisions and tags cannot cause the loop. Being of a
	# fundamentally different type they cannot be in the incoming
	# set of ids.

	set theset ('[join $branches {','}]')
	return [state run [subst -nocommands -nobackslashes {
	    SELECT B.bid, BX.bid
	    FROM   branch B, preferedparent P, branch BX
	    WHERE  B.bid IN $theset   -- Restrict to branches of interest
	    AND    B.sid = P.pid      -- Get the prefered branches via
	    AND    BX.sid = P.sid     -- the branch symbols
	    AND    BX.bid IN $theset  -- Loop
	}]]
    }

    # var(dv) = dict (item -> list (item)), item  = list (type id)
    typemethod successors {dv branches} {
	upvar 1 $dv dependencies
	# The first revision committed on a branch, and all branches
................................................................................
	# and tags which have it as their prefered parent are the
	# successors of a branch.

	set theset ('[join $branches {','}]')
	foreach {bid child} [state run [subst -nocommands -nobackslashes {
	    SELECT B.bid, R.rid
	    FROM   branch B, revision R
	    WHERE  B.bid IN $theset     -- Restrict to branches of interest
	    AND    B.first = R.rid      -- Get first revision on the branch
	}]] {
	    lappend dependencies([list sym::branch $bid]) [list rev $child]
	}
	foreach {bid child} [state run [subst -nocommands -nobackslashes {
	    SELECT B.bid, BX.bid
	    FROM   branch B, preferedparent P, branch BX
	    WHERE  B.bid IN $theset     -- Restrict to branches of interest
	    AND    B.sid = P.pid        -- Get subordinate branches via the
	    AND    BX.sid = P.sid       -- prefered parents of their symbols
	}]] {
	    lappend dependencies([list sym::branch $bid]) [list sym::branch $child]
	}
	foreach {bid child} [state run [subst -nocommands -nobackslashes {
	    SELECT B.bid, T.tid
	    FROM   branch B, preferedparent P, tag T
	    WHERE  B.bid IN $theset     -- Restrict to branches of interest
	    AND    B.sid = P.pid        -- Get subordinate tags via the
	    AND    T.sid = P.sid        -- prefered parents of their symbols
	}]] {
	    lappend dependencies([list sym::branch $bid]) [list sym::tag $child]
	}
	return
    }

    # result = list (changeset-id)
................................................................................
        # CVS)) we return a very short and much more manageable list
        # of changesets.

	set theset ('[join $branches {','}]')
        return [state run [subst -nocommands -nobackslashes {
	    SELECT C.cid
	    FROM   branch B, revision R, csitem CI, changeset C
	    WHERE  B.bid IN $theset     -- Restrict to branches of interest
	    AND    B.first = R.rid	-- Get first revision on the branch
            AND    CI.iid = R.rid       -- Select all changesets
            AND    C.cid = CI.cid	-- containing this revision
            AND    C.type = 0		-- which are revision changesets
    UNION
	    SELECT C.cid
	    FROM   branch B, preferedparent P, branch BX, csitem CI, changeset C
	    WHERE  B.bid IN $theset     -- Restrict to branches of interest
	    AND    B.sid = P.pid	-- Get subordinate branches via the
	    AND    BX.sid = P.sid	-- prefered parents of their symbols
            AND    CI.iid = BX.bid      -- Select all changesets
            AND    C.cid = CI.cid	-- containing the subordinate branches
            AND    C.type = 2		-- which are branch changesets
    UNION
	    SELECT C.cid
	    FROM   branch B, preferedparent P, tag T, csitem CI, changeset C
	    WHERE  B.bid IN $theset     -- Restrict to branches of interest
	    AND    B.sid = P.pid	-- Get subordinate tags via the
	    AND    T.sid = P.sid	-- prefered parents of their symbols
            AND    CI.iid = T.tid       -- Select all changesets
            AND    C.cid = CI.cid	-- containing the subordinate tags
            AND    C.type = 1		-- which are tag changesets
	}]]
	return
    }

    typemethod limits {branches} {
	# Notes. This method exists only for branches. It is needed to
	# get detailed information about a backward branch. It does
................................................................................

	set theset ('[join $branches {','}]')

	set maxp [state run [subst -nocommands -nobackslashes {
	    -- maximal predecessor position per branch
	    SELECT B.bid, MAX (CO.pos)
	    FROM   branch B, revision R, csitem CI, changeset C, csorder CO
	    WHERE  B.bid IN $theset     -- Restrict to branches of interest
	    AND    B.root = R.rid       -- Get branch root revisions
	    AND    CI.iid = R.rid       -- Get changesets containing the
	    AND    C.cid = CI.cid       -- root revisions, which are
	    AND    C.type = 0           -- revision changesets
	    AND    CO.cid = C.cid       -- Get their topological ordering
	    GROUP BY B.bid
	}]]

	set mins [state run [subst -nocommands -nobackslashes {
	    -- minimal successor position per branch
	    SELECT B.bid, MIN (CO.pos)
	    FROM   branch B, revision R, csitem CI, changeset C, csorder CO
	    WHERE  B.bid IN $theset     -- Restrict to branches of interest
	    AND    B.first = R.rid      -- Get the first revisions on the branches
	    AND    CI.iid = R.rid       -- Get changesets containing the
	    AND    C.cid = CI.cid	-- first revisions, which are
	    AND    C.type = 0		-- revision changesets
	    AND    CO.cid = C.cid	-- Get their topological ordering
	    GROUP BY B.bid
	}]]

        return [list $maxp $mins]
    }

    # # ## ### ##### ######## #############

Changes to tools/cvs2fossil/lib/c2f_repository.tcl.

277
278
279
280
281
282
283
284
285
286
287
288
289
290
291


    # pass IV+ results
    typemethod printcsetstatistics {} {
	log write 2 repository "Changeset statistics"
	# number of revisions, symbols, repository wide, and per project ...

	set ccount [state one { SELECT COUNT (*) FROM changeset                 }]
	set rcount [state one { SELECT COUNT (*) FROM changeset WHERE type = 0 }]
	set tcount [state one { SELECT COUNT (*) FROM changeset WHERE type = 1 }]
	set bcount [state one { SELECT COUNT (*) FROM changeset WHERE type = 2 }]
	set fmt %[string length [max [list $ccount $rcount $tcount $bcount]]]s

	log write 2 repository "Statistics: [format $fmt $ccount] [sp $ccount changeset]"
	log write 2 repository "Statistics: [format $fmt $rcount] [sp $rcount {revision changeset}]"







|







277
278
279
280
281
282
283
284
285
286
287
288
289
290
291


    # pass IV+ results
    typemethod printcsetstatistics {} {
	log write 2 repository "Changeset statistics"
	# number of revisions, symbols, repository wide, and per project ...

	set ccount [state one { SELECT COUNT (*) FROM changeset                }]
	set rcount [state one { SELECT COUNT (*) FROM changeset WHERE type = 0 }]
	set tcount [state one { SELECT COUNT (*) FROM changeset WHERE type = 1 }]
	set bcount [state one { SELECT COUNT (*) FROM changeset WHERE type = 2 }]
	set fmt %[string length [max [list $ccount $rcount $tcount $bcount]]]s

	log write 2 repository "Statistics: [format $fmt $ccount] [sp $ccount changeset]"
	log write 2 repository "Statistics: [format $fmt $rcount] [sp $rcount {revision changeset}]"