Needs["CSM`DB`"]

(* non default attribute types and prompts *)

Type[recKey] ^= Expression
Type[workKey] ^= Expression
Type[artistKey] ^= Expression
Type[compKey] ^= Expression

database = ToFileName["CSM", "music.db"]

load := (Get[database];)

save := (
	DeleteFile[database <> ".bak"];
	RenameFile[database, database <> ".bak"];
	Save[ database, allRelations ];
	database
	)

layout = {
	{ recordings, {recKey, workKey, recordNumber}},
	{ performers, {recKey, artistKey}},
	{ works,      {workKey, compKey, workTitle}},
	{ composers,  {compKey, composerName}},
	{ artists,    {artistKey, artistName, instrument}},
	{ records,    {recordTitle, label, recordNumber}}
}

init := (
	allRelations = First /@ layout;
	Apply[ (#1 = newRelation[#2])&, layout, {1} ]
	)


(* standard reports *)

report[ allrecords ] :=
	Module[{rel},
		rel = records;
		rel = Join[ rel, recordings ];
		rel = Join[ rel, works ];
		rel = Join[ rel, composers ];
		rel = Projection[ rel,
			{recordTitle, label, recordNumber,
			 composerName, workTitle} ];
		Report[rel, 3, 1]
	]

report[ allperf ] :=
	Module[{rel},
		rel = records;
		rel = Join[ rel, recordings ];
		rel = Join[ rel, works ];
		rel = Join[ rel, composers ];
		rel = Join[ rel, performers ];
		rel = Join[ rel, artists ];
		rel = Projection[ rel,
			{recordNumber, recordTitle, composerName,
			 workTitle, artistName, instrument} ];
		Report[rel, 2, 1, 1, 2]
	]

report[ allworks ] :=
	Module[{rel},
		rel = recordings;
		rel = Join[ rel, works ];
		rel = Join[ rel, composers ];
		rel = Join[ rel, performers ];
		rel = Join[ rel, artists ];
		rel = Projection[ rel,
			{composerName, workTitle,
			 recordNumber, artistName, instrument}];
		Report[rel, 1, 1, 1, 2]
	]

report[ allartists ] :=
	Module[{rel},
		rel = recordings;
		rel = Join[ rel, works ];
		rel = Join[ rel, composers ];
		rel = Join[ rel, performers ];
		rel = Join[ rel, artists ];
		rel = Projection[ rel,
			{artistName, instrument, composerName,
			workTitle, recordNumber}];
		Report[rel, 2, 1, 2]
	]

rules[rel_, rec_List] := Thread[ Fields[rel] -> rec ]

DataEntry :=
    Module[{record, recno, work, workt, workk,
            perfk, artist, ak},
    While[ True, (* loop over records *)
        record = FindOrAdd[ records, {recordNumber} ];
    	If[ record === EndOfFile, Break[] ];
    	recno = recordNumber /. rules[ records, record ];
    	While[ True, (* loop over works/recordings *)
    	    Print["next work on record ", recno];
    	    composer = FindOrAdd[ composers, {composerName},
    	                          {}, compKey ];
    	    If[ composer === EndOfFile, Break[] ];
    	    compk = compKey /. rules[ composers, composer ];
    	    work = FindOrAdd[ works, {workTitle},
    	                      {compKey->compk}, workKey ];
    	    If[ work === EndOfFile, Break[] ];
    	    workk = workKey /. rules[ works, work ];
    	    workt = workTitle /. rules[ works, work ];
    	    perfk = addWithKeyTo[ recordings, {workk, recno},
    	                        recKey ];
    	    While[ True, (* loop over artists *)
    	        Print["next performer of ", workt];
    	        artist = FindOrAdd[ artists, {artistName, instrument},
    	                            {}, artistKey ];
    	        If[ artist === EndOfFile, Break[] ];
    	        ak = artistKey /. rules[ artists, artist ];
    	        addTupleTo[ performers, {perfk, ak} ]
    	    ]
        ];
        Print[""];
    ]
    ]
