From f23da7c016f907e45abba3a954d7b10220b208ed Mon Sep 17 00:00:00 2001 From: Diomidis Spinellis Date: Fri, 12 Jul 2024 20:17:49 +0300 Subject: [PATCH] Add option to specify which SQL tables to generate --- man/cscout.1 | 14 +- src/call.cpp | 50 ++-- src/cscout.cpp | 13 +- src/fdep.cpp | 66 ++--- src/globobj.cpp | 49 ++-- src/workdb.cpp | 633 ++++++++++++++++++++++++++++-------------------- src/workdb.h | 33 +++ 7 files changed, 514 insertions(+), 344 deletions(-) diff --git a/man/cscout.1 b/man/cscout.1 index 8d4fcf81..15b50a2e 100644 --- a/man/cscout.1 +++ b/man/cscout.1 @@ -1,4 +1,4 @@ -.TH CSCOUT 1 "25 April 2024" +.TH CSCOUT 1 "12 July 2024" .\" .\" (C) Copyright 2003-2024 Diomidis Spinellis .\" @@ -29,6 +29,7 @@ cscout \- C code analyzer and refactoring browser [\fB\-p\fP \fIport\fP] [\fB\-R\fP \fIspecification\fP] [\fB\-m\fP \fIspecification\fP] +[\fB\-t\fP \fIsname\fP] [\fB\-o\fP | \fB\-s\fP \fIdb\fP] \fIfile\fR .SH DESCRIPTION @@ -239,6 +240,15 @@ dot -Tsvg >cgraph.svg .fi .DE +.IP "\fB\-t\fP \fIname\fP" +Generate SQL output for the named table. +By default SQL output for all tables is generated. +If this option is provided, then output only for the specified tables +will be generated. +It is the user's responsibility to list the tables required to avoid +breaking integrity constraints. +The option can be specified multiple times. + .IP "\fB\-o\fP" Create obfuscated versions of all the writable files of the workspace. .PP @@ -325,4 +335,4 @@ We are now ready to serve you at http://localhost:8081 .SH "SEE ALSO" cswc(1) .SH AUTHOR -(c) Copyright 2003-2015 Diomidis Spinellis. +(c) Copyright 2003-2024 Diomidis Spinellis. diff --git a/src/call.cpp b/src/call.cpp index 7ecfa32f..b170fc2b 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -55,6 +55,7 @@ #include "mcall.h" #include "eclass.h" #include "sql.h" +#include "workdb.h" // Function currently being parsed Call *Call::current_fun = NULL; @@ -253,19 +254,20 @@ Call::dumpSql(Sql *db, ostream &of) for (const_fmap_iterator_type i = fbegin(); i != fend(); i++) { Call *fun = i->second; Tokid t = fun->get_site(); - of << "INSERT INTO FUNCTIONS VALUES(" << - ptr_offset(fun) << ", '" << - fun->name << "', " << - db->boolval(fun->is_macro()) << ',' << - db->boolval(fun->is_defined()) << ',' << - db->boolval(fun->is_declared()) << ',' << - db->boolval(fun->is_file_scoped()) << ',' << - t.get_fileid().get_id() << ',' << - (unsigned)(t.get_streampos()) << ',' << - fun->get_num_caller(); - of << ");\n"; + if (table_is_enabled(t_functions)) + of << "INSERT INTO FUNCTIONS VALUES(" + << ptr_offset(fun) << ", '" + << fun->name << "', " + << db->boolval(fun->is_macro()) << ',' + << db->boolval(fun->is_defined()) << ',' + << db->boolval(fun->is_declared()) << ',' + << db->boolval(fun->is_file_scoped()) << ',' + << t.get_fileid().get_id() << ',' + << (unsigned)(t.get_streampos()) << ',' + << fun->get_num_caller() + << ");\n"; - if (fun->is_defined()) { + if (fun->is_defined() && table_is_enabled(t_functionmetrics)) { of << "INSERT INTO FUNCTIONMETRICS VALUES(" << ptr_offset(fun); for (int j = 0; j < FunMetrics::metric_max; j++) if (!Metrics::is_internal(j)) @@ -284,10 +286,11 @@ Call::dumpSql(Sql *db, ostream &of) int pos = 0; while (pos < len) { Eclass *ec = t2.get_ec(); - of << "INSERT INTO FUNCTIONID VALUES(" << - ptr_offset(fun) << ',' << - ord << ',' << - ptr_offset(ec) << ");\n"; + if (table_is_enabled(t_functionid)) + of << "INSERT INTO FUNCTIONID VALUES(" + << ptr_offset(fun) << ',' + << ord << ',' + << ptr_offset(ec) << ");\n"; pos += ec->get_len(); t2 += ec->get_len(); ord++; @@ -297,11 +300,12 @@ Call::dumpSql(Sql *db, ostream &of) } // Then their calls to satisfy integrity constraints - for (const_fmap_iterator_type i = fbegin(); i != fend(); i++) { - Call *fun = i->second; - for (Call::const_fiterator_type dest = fun->call_begin(); dest != fun->call_end(); dest++) - of << "INSERT INTO FCALLS VALUES(" << - ptr_offset(fun) << ',' << - ptr_offset(*dest) << ");\n"; - } + if (table_is_enabled(t_fcalls)) + for (const_fmap_iterator_type i = fbegin(); i != fend(); i++) { + Call *fun = i->second; + for (Call::const_fiterator_type dest = fun->call_begin(); dest != fun->call_end(); dest++) + of << "INSERT INTO FCALLS VALUES(" << + ptr_offset(fun) << ',' << + ptr_offset(*dest) << ");\n"; + } } diff --git a/src/cscout.cpp b/src/cscout.cpp index 860b60b2..f049baf3 100644 --- a/src/cscout.cpp +++ b/src/cscout.cpp @@ -3276,7 +3276,7 @@ main(int argc, char *argv[]) vector call_graphs; Debug::db_read(); - while ((c = getopt(argc, argv, "3bCcd:rvE:P:p:m:l:os:R:" PICO_QL_OPTIONS)) != EOF) + while ((c = getopt(argc, argv, "3bCcd:rvE:P:p:m:l:oR:s:t:" PICO_QL_OPTIONS)) != EOF) switch (c) { case '3': Fchar::enable_trigraphs(); @@ -3367,6 +3367,11 @@ main(int argc, char *argv[]) process_mode = pm_database; db_engine = strdup(optarg); break; + case 't': + if (!optarg) + usage(argv[0]); + table_enable(optarg); + break; case 'R': if (!optarg) usage(argv[0]); @@ -3396,7 +3401,7 @@ main(int argc, char *argv[]) parse_acl(); } - if (db_engine) { + if (process_mode == pm_database) { if (!Sql::setEngine(db_engine)) return 1; cout << Sql::getInterface()->begin_commands(); @@ -3474,7 +3479,7 @@ main(int argc, char *argv[]) if (DP()) cout << "Size " << file_msum.get_total(Metrics::em_nchar) << endl; - if (Sql::getInterface()) { + if (process_mode == pm_database) { workdb_rest(Sql::getInterface(), cout); Call::dumpSql(Sql::getInterface(), cout); cout << Sql::getInterface()->end_commands(); @@ -3660,7 +3665,7 @@ garbage_collect(Fileid root) for (set ::const_iterator i = touched_files.begin(); i != touched_files.end(); i++) if (*i != root && *i != input_file_id) root.includes(*i, /* directly included (conservatively) */ false, i->required()); - if (Sql::getInterface()) + if (process_mode == pm_database) Fdep::dumpSql(Sql::getInterface(), root); Fdep::reset(); diff --git a/src/fdep.cpp b/src/fdep.cpp index 942b4b6d..40605781 100644 --- a/src/fdep.cpp +++ b/src/fdep.cpp @@ -37,7 +37,9 @@ #include "fileid.h" #include "tokid.h" #include "fdep.h" +#include "workdb.h" #include "sql.h" +#include "workdb.h" /* * These are serially set for each processed file, and @@ -105,37 +107,41 @@ Fdep::reset() void Fdep::dumpSql(Sql *db, Fileid cu) { - for (FSFMap::const_iterator di = definers.begin(); di != definers.end(); di++) { - const set &defs = di->second; - for (set ::const_iterator i = defs.begin(); i != defs.end(); i++) - cout << "INSERT INTO DEFINERS VALUES(" << - Project::get_current_projid() << ',' << - cu.get_id() << ',' << - di->first.get_id() << ',' << - i->get_id() << ");\n"; - } - for (FSFMap::const_iterator ii = includers.begin(); ii != includers.end(); ii++) { - const set &incs = ii->second; - for (set ::const_iterator i = incs.begin(); i != incs.end(); i++) - cout << "INSERT INTO INCLUDERS VALUES(" << + if (table_is_enabled(t_definers)) + for (FSFMap::const_iterator di = definers.begin(); di != definers.end(); di++) { + const set &defs = di->second; + for (set ::const_iterator i = defs.begin(); i != defs.end(); i++) + cout << "INSERT INTO DEFINERS VALUES(" << + Project::get_current_projid() << ',' << + cu.get_id() << ',' << + di->first.get_id() << ',' << + i->get_id() << ");\n"; + } + if (table_is_enabled(t_includers)) + for (FSFMap::const_iterator ii = includers.begin(); ii != includers.end(); ii++) { + const set &incs = ii->second; + for (set ::const_iterator i = incs.begin(); i != incs.end(); i++) + cout << "INSERT INTO INCLUDERS VALUES(" << + Project::get_current_projid() << ',' << + cu.get_id() << ',' << + ii->first.get_id() << ',' << + i->get_id() << ");\n"; + } + if (table_is_enabled(t_providers)) + for (set ::const_iterator i = providers.begin(); i != providers.end(); i++) + cout << "INSERT INTO PROVIDERS VALUES(" << Project::get_current_projid() << ',' << cu.get_id() << ',' << - ii->first.get_id() << ',' << i->get_id() << ");\n"; - } - for (set ::const_iterator i = providers.begin(); i != providers.end(); i++) - cout << "INSERT INTO PROVIDERS VALUES(" << - Project::get_current_projid() << ',' << - cu.get_id() << ',' << - i->get_id() << ");\n"; - for (ITMap::const_iterator i = include_triggers.begin(); i != include_triggers.end(); i++) - for (include_trigger_value::const_iterator j = i->second.begin(); j != i->second.end(); j++) { - cout << "INSERT INTO INCTRIGGERS VALUES(" << - Project::get_current_projid() << ',' << - cu.get_id() << ',' << - i->first.second.get_id() << ',' << - i->first.first.get_id() << ',' << - (unsigned)(j->first) << ',' << - j->second << ");\n"; - } + if (table_is_enabled(t_inctriggers)) + for (ITMap::const_iterator i = include_triggers.begin(); i != include_triggers.end(); i++) + for (include_trigger_value::const_iterator j = i->second.begin(); j != i->second.end(); j++) { + cout << "INSERT INTO INCTRIGGERS VALUES(" << + Project::get_current_projid() << ',' << + cu.get_id() << ',' << + i->first.second.get_id() << ',' << + i->first.first.get_id() << ',' << + (unsigned)(j->first) << ',' << + j->second << ");\n"; + } } diff --git a/src/globobj.cpp b/src/globobj.cpp index c476759c..b833d13a 100644 --- a/src/globobj.cpp +++ b/src/globobj.cpp @@ -118,19 +118,20 @@ GlobObj::dumpSql(Sql *db, ostream &of) for (const_fmap_iterator_type i = fbegin(); i != fend(); i++) { Call *fun = i->second; Tokid t = fun->get_site(); - of << "INSERT INTO FUNCTIONS VALUES(" << - ptr_offset(fun) << ", '" << - fun->name << "', " << - db->boolval(fun->is_macro()) << ',' << - db->boolval(fun->is_defined()) << ',' << - db->boolval(fun->is_declared()) << ',' << - db->boolval(fun->is_file_scoped()) << ',' << - t.get_fileid().get_id() << ',' << - (unsigned)(t.get_streampos()) << ',' << - fun->get_num_caller(); - of << ");\n"; + if (table_is_enabled(t_functions)) + of << "INSERT INTO FUNCTIONS VALUES(" << + ptr_offset(fun) << ", '" << + fun->name << "', " << + db->boolval(fun->is_macro()) << ',' << + db->boolval(fun->is_defined()) << ',' << + db->boolval(fun->is_declared()) << ',' << + db->boolval(fun->is_file_scoped()) << ',' << + t.get_fileid().get_id() << ',' << + (unsigned)(t.get_streampos()) << ',' << + fun->get_num_caller(); + of << ");\n"; - if (fun->is_defined()) { + if (fun->is_defined() && table_is_enabled(t_functionmetrics)) { of << "INSERT INTO FUNCTIONMETRICS VALUES(" << ptr_offset(fun); for (int j = 0; j < FunMetrics::metric_max; j++) if (!Metrics::is_internal(j)) @@ -149,10 +150,11 @@ GlobObj::dumpSql(Sql *db, ostream &of) int pos = 0; while (pos < len) { Eclass *ec = t2.get_ec(); - of << "INSERT INTO FUNCTIONID VALUES(" << - ptr_offset(fun) << ',' << - ord << ',' << - ptr_offset(ec) << ");\n"; + if (table_is_enabled(t_functionid)) + of << "INSERT INTO FUNCTIONID VALUES(" << + ptr_offset(fun) << ',' << + ord << ',' << + ptr_offset(ec) << ");\n"; pos += ec->get_len(); t2 += ec->get_len(); ord++; @@ -162,12 +164,13 @@ GlobObj::dumpSql(Sql *db, ostream &of) } // Then their calls to satisfy integrity constraints - for (const_fmap_iterator_type i = fbegin(); i != fend(); i++) { - Call *fun = i->second; - for (Call::const_fiterator_type dest = fun->call_begin(); dest != fun->call_end(); dest++) - of << "INSERT INTO FCALLS VALUES(" << - ptr_offset(fun) << ',' << - ptr_offset(*dest) << ");\n"; - } + if (table_is_enabled(t_fcalls)) + for (const_fmap_iterator_type i = fbegin(); i != fend(); i++) { + Call *fun = i->second; + for (Call::const_fiterator_type dest = fun->call_begin(); dest != fun->call_end(); dest++) + of << "INSERT INTO FCALLS VALUES(" << + ptr_offset(fun) << ',' << + ptr_offset(*dest) << ");\n"; + } } #endif /* TODO */ diff --git a/src/workdb.cpp b/src/workdb.cpp index 079ff9ca..e95b6269 100644 --- a/src/workdb.cpp +++ b/src/workdb.cpp @@ -59,6 +59,61 @@ #include "sql.h" #include "workdb.h" +// Tables that are disabled (by default none) +static bool disabled_tables[table_max]; + +// Enable output of the specified table +void +table_enable(const char *name) +{ + static bool initialized; + static map table_enum; + + + if (!initialized) { + // On first call disable all tables + for (int i = 0; i < table_max; i++) + disabled_tables[i] = true; + + table_enum["IDS"] = t_ids; + table_enum["FILES"] = t_files; + table_enum["TOKENS"] = t_tokens; + table_enum["COMMENTS"] = t_comments; + table_enum["STRINGS"] = t_strings; + table_enum["REST"] = t_rest; + table_enum["LINEPOS"] = t_linepos; + table_enum["PROJECTS"] = t_projects; + table_enum["IDPROJ"] = t_idproj; + table_enum["FILEPROJ"] = t_fileproj; + table_enum["DEFINERS"] = t_definers; + table_enum["INCLUDERS"] = t_includers; + table_enum["PROVIDERS"] = t_providers; + table_enum["INCTRIGGERS"] = t_inctriggers; + table_enum["FUNCTIONS"] = t_functions; + table_enum["FUNCTIONMETRICS"] = t_functionmetrics; + table_enum["FUNCTIONID"] = t_functionid; + table_enum["FCALLS"] = t_fcalls; + table_enum["FILECOPIES"] = t_filecopies; + + initialized = true; + } + + auto f = table_enum.find(name); + if (f == table_enum.end()) { + cerr << "Unkown table name " << name << endl; + exit(1); + } + disabled_tables[f->second] = false; +} + +// Return true if the specified table is enabled +bool +table_is_enabled(enum e_table t) +{ + return !disabled_tables[t]; +} + + // Our identifiers to store as a set class Identifier { Eclass *ec; // Equivalence class it belongs to @@ -93,30 +148,32 @@ insert_eclass(Sql *db, ostream &of, Eclass *e, const string &name) // Update metrics id_msum.add_unique_id(e); - of << "INSERT INTO IDS VALUES(" << - ptr_offset(e) << ",'" << - name << "'," << - db->boolval(e->get_attribute(is_readonly)) << ',' << - db->boolval(e->get_attribute(is_undefined_macro)) << ',' << - db->boolval(e->get_attribute(is_macro)) << ',' << - db->boolval(e->get_attribute(is_macro_arg)) << ',' << - db->boolval(e->get_attribute(is_ordinary)) << ',' << - db->boolval(e->get_attribute(is_suetag)) << ',' << - db->boolval(e->get_attribute(is_sumember)) << ',' << - db->boolval(e->get_attribute(is_label)) << ',' << - db->boolval(e->get_attribute(is_typedef)) << ',' << - db->boolval(e->get_attribute(is_enumeration)) << ',' << - db->boolval(e->get_attribute(is_yacc)) << ',' << - db->boolval(e->get_attribute(is_cfunction)) << ',' << - db->boolval(e->get_attribute(is_cscope)) << ',' << - db->boolval(e->get_attribute(is_lscope)) << ',' << - db->boolval(e->is_unused()) << - ");\n"; + if (table_is_enabled(t_ids)) + of << "INSERT INTO IDS VALUES(" << + ptr_offset(e) << ",'" << + name << "'," << + db->boolval(e->get_attribute(is_readonly)) << ',' << + db->boolval(e->get_attribute(is_undefined_macro)) << ',' << + db->boolval(e->get_attribute(is_macro)) << ',' << + db->boolval(e->get_attribute(is_macro_arg)) << ',' << + db->boolval(e->get_attribute(is_ordinary)) << ',' << + db->boolval(e->get_attribute(is_suetag)) << ',' << + db->boolval(e->get_attribute(is_sumember)) << ',' << + db->boolval(e->get_attribute(is_label)) << ',' << + db->boolval(e->get_attribute(is_typedef)) << ',' << + db->boolval(e->get_attribute(is_enumeration)) << ',' << + db->boolval(e->get_attribute(is_yacc)) << ',' << + db->boolval(e->get_attribute(is_cfunction)) << ',' << + db->boolval(e->get_attribute(is_cscope)) << ',' << + db->boolval(e->get_attribute(is_lscope)) << ',' << + db->boolval(e->is_unused()) << + ");\n"; // The projects each EC belongs to - for (unsigned j = attr_end; j < Attributes::get_num_attributes(); j++) - if (e->get_attribute(j)) - of << "INSERT INTO IDPROJ VALUES(" << - ptr_offset(e) << ',' << j << ");\n"; + if (table_is_enabled(t_idproj)) + for (unsigned j = attr_end; j < Attributes::get_num_attributes(); j++) + if (e->get_attribute(j)) + of << "INSERT INTO IDPROJ VALUES(" + << ptr_offset(e) << ',' << j << ");\n"; } // Chunk the input into tables @@ -130,33 +187,37 @@ class Chunker { streampos startpos; // Starting position of current chunk string chunk; // Characters accumulated in the current chunk public: - Chunker(fifstream &i, Sql *d, ostream &o, Fileid f) : in(i), table("REST"), db(d), of(o), fid(f), startpos(0) {} + bool enabled; // True if output to the table is enabled + Chunker(fifstream &i, Sql *d, ostream &o, Fileid f) : in(i), table("REST"), db(d), of(o), fid(f), startpos(0), enabled(table_is_enabled(t_rest)) {} // Flush the currently collected input into the database // Should be called at the point where new input is expected void flush() { if (chunk.length() > 0) { - of << "INSERT INTO " << table << " VALUES(" << - fid.get_id() << - "," << (unsigned)startpos << - ",'" << chunk << "');\n"; + if (enabled) + of << "INSERT INTO " << table << " VALUES(" + << fid.get_id() + << "," << (unsigned)startpos + << ",'" << chunk << "');\n"; chunk.erase(); } startpos = in.tellg(); } // Start collecting input for a (possibly) new table + // e specifies whether the table is enabled // Should be called at the point where new input is expected // s can be input already collected - void start(const char *t, const string &s = string("")) { + void start(const char *t, bool e, const string &s = string("")) { flush(); table = string(t); startpos -= s.length(); chunk = db->escape(s); + enabled = e; } - void start(const char *t, char c) { - start(t, string(1, c)); + void start(const char *t, bool e, char c) { + start(t, e, string(1, c)); } inline void add(char c) { @@ -207,9 +268,11 @@ file_dump(Sql *db, ostream &of, Fileid fid) insert_eclass(db, of, ec, s); fid.metrics().process_id(s, ec); chunker.flush(); - of << "INSERT INTO TOKENS VALUES(" << fid.get_id() << - "," << (unsigned)ti.get_streampos() << "," << - ptr_offset(ec) << ");\n"; + if (table_is_enabled(t_tokens)) + of << "INSERT INTO TOKENS VALUES(" + << fid.get_id() << "," + << (unsigned)ti.get_streampos() << "," + << ptr_offset(ec) << ");\n"; } else { fid.metrics().process_char(c); if (c == '\n') { @@ -218,10 +281,12 @@ file_dump(Sql *db, ostream &of, Fileid fid) line_number++; } else { if (at_bol) { - of << "INSERT INTO LINEPOS VALUES(" << - fid.get_id() << - "," << (unsigned)bol << - "," << line_number << ");\n"; + if (table_is_enabled(t_linepos)) + of << "INSERT INTO LINEPOS VALUES(" + << fid.get_id() + << "," << (unsigned)bol + << "," << line_number + << ");\n"; at_bol = false; } } @@ -231,7 +296,7 @@ file_dump(Sql *db, ostream &of, Fileid fid) cstate = s_saw_slash; else if (c == '"') { cstate = s_string; - chunker.start("STRINGS", c); + chunker.start("STRINGS", table_is_enabled(t_strings), c); } else if (c == '\'') { cstate = s_char; chunker.add(c); @@ -249,7 +314,7 @@ file_dump(Sql *db, ostream &of, Fileid fid) chunker.add(c); if (c == '"') { cstate = s_normal; - chunker.start("REST"); + chunker.start("REST", table_is_enabled(t_rest)); } else if (c == '\\') cstate = s_saw_str_backslash; break; @@ -264,10 +329,10 @@ file_dump(Sql *db, ostream &of, Fileid fid) case s_saw_slash: // After a / character if (c == '/') { cstate = s_cpp_comment; - chunker.start("COMMENTS", "//"); + chunker.start("COMMENTS", table_is_enabled(t_comments), "//"); } else if (c == '*') { cstate = s_block_comment; - chunker.start("COMMENTS", "/*"); + chunker.start("COMMENTS", table_is_enabled(t_comments), "/*"); } else { chunker.add('/'); chunker.add(c); @@ -278,7 +343,7 @@ file_dump(Sql *db, ostream &of, Fileid fid) chunker.add(c); if (c == '\n') { cstate = s_normal; - chunker.start("REST"); + chunker.start("REST", table_is_enabled(t_rest)); } break; case s_block_comment: // Inside C block comment @@ -290,7 +355,7 @@ file_dump(Sql *db, ostream &of, Fileid fid) chunker.add(c); if (c == '/') { cstate = s_normal; - chunker.start("REST"); + chunker.start("REST", table_is_enabled(t_rest)); } else if (c != '*') cstate = s_block_comment; break; @@ -306,207 +371,245 @@ file_dump(Sql *db, ostream &of, Fileid fid) void workdb_schema(Sql *db, ostream &of) { - cout << - // BEGIN AUTOSCHEMA - "CREATE TABLE IDS(" // Details of interdependant identifiers appearing in the workspace - "EID " << db->ptrtype() << " PRIMARY KEY," // Unique identifier key - "NAME " << db->varchar() << "," // Identifier name - "READONLY " << db->booltype() << ", " // True if it appears in at least one read-only file - "UNDEFMACRO " << db->booltype() << ", " // True if it is apparantly an undefined macro - "MACRO " << db->booltype() << ", " // True if it a preprocessor macro - "MACROARG " << db->booltype() << ", " // True if it a preprocessor macro argument - "ORDINARY " << db->booltype() << ", " // True if it is an ordinary identifier (variable or function) - "SUETAG " << db->booltype() << ", " // True if it is a structure, union, or enumeration tag - "SUMEMBER " << db->booltype() << ", " // True if it is a structure or union member - "LABEL " << db->booltype() << ", " // True if it is a label - "TYPEDEF " << db->booltype() << ", " // True if it is a typedef - "ENUM " << db->booltype() << ", " // True if it is an enumeration member - "YACC " << db->booltype() << ", " // True if it is a yacc identifier - "FUN " << db->booltype() << ", " // True if it is a function name - "CSCOPE " << db->booltype() << ", " // True if its scope is a compilation unit - "LSCOPE " << db->booltype() << ", " // True if it has linkage scope - "UNUSED " << db->booltype() << // True if it is not used - ");\n" - - "CREATE TABLE FILES(" // File details - "FID INTEGER PRIMARY KEY," // Unique file key - "NAME " << db->varchar() << ",\n" // File name - "RO " << db->booltype(); // True if the file is read-only - // AUTOSCHEMA INCLUDE metrics.cpp Metrics - // AUTOSCHEMA INCLUDE filemetrics.cpp FileMetrics - for (int i = 0; i < FileMetrics::metric_max; i++) - if (!Metrics::is_internal(i)) - cout << ",\n" << Metrics::get_dbfield(i) << " INTEGER"; - cout << ");\n" - - "CREATE TABLE TOKENS(" // Instances of identifier tokens within the source code - "FID INTEGER," // File key (references FILES) - "FOFFSET INTEGER," // Offset within the file - "EID " << db->ptrtype() << ",\n" // Identifier key (references IDS) - "PRIMARY KEY(FID, FOFFSET)," - "FOREIGN KEY(FID) REFERENCES FILES(FID)," - "FOREIGN KEY(EID) REFERENCES IDS(EID)" - ");\n" - - "CREATE TABLE COMMENTS(" // Comments in the code - "FID INTEGER," // File key (references FILES) - "FOFFSET INTEGER," // Offset within the file - "COMMENT " << db->varchar() << "," // The comment, including its delimiters - "PRIMARY KEY(FID, FOFFSET)," - "FOREIGN KEY(FID) REFERENCES FILES(FID)" - ");\n" - - "CREATE TABLE STRINGS(" // Strings in the code - "FID INTEGER," // File key (references FILES) - "FOFFSET INTEGER," // Offset within the file - "STRING " << db->varchar() << "," // The string, including its delimiters - "PRIMARY KEY(FID, FOFFSET)," - "FOREIGN KEY(FID) REFERENCES FILES(FID)" - ");\n" - - "CREATE TABLE REST(" // Remaining, non-identifier source code - "FID INTEGER," // File key (references FILES) - "FOFFSET INTEGER," // Offset within the file - "CODE " << db->varchar() << "," // The actual code - "PRIMARY KEY(FID, FOFFSET)," - "FOREIGN KEY(FID) REFERENCES FILES(FID)" - ");\n" - - "CREATE TABLE LINEPOS(" // Line number offsets within each file - "FID INTEGER," // File key (references FILES) - "FOFFSET INTEGER," // Offset within the file - "LNUM INTEGER," // Line number (starts at 1) - "PRIMARY KEY(FID, FOFFSET)," - "FOREIGN KEY(FID) REFERENCES FILES(FID)" - ");\n" - - - "CREATE TABLE PROJECTS(" // Project details - "PID INTEGER PRIMARY KEY," // Unique project key - "NAME " << db->varchar() << // Project name - ");\n" - - "CREATE TABLE IDPROJ(" // Identifiers appearing in projects - "EID " << db->ptrtype() << "," // Identifier key (references IDS) - "PID INTEGER," // Project key (references PROJECTS) - "FOREIGN KEY(EID) REFERENCES IDS(EID)," - "FOREIGN KEY(PID) REFERENCES PROJECTS(PID)" - ");\n" - - "CREATE TABLE FILEPROJ(" // Files used in projects - "FID INTEGER, " // File key (references FILES) - "PID INTEGER," // Project key (references PROJECTS) - "FOREIGN KEY(FID) REFERENCES FILES(FID)," - "FOREIGN KEY(PID) REFERENCES PROJECTS(PID)" - ");\n" - - /* - * Foreign keys for the following four tables are not specified, because it is difficult - * to satisfy integrity constraints: files (esp. their metrics, esp. ncopies) can't - * be written until the end of processing, while to conserve space, these tables are - * written after each file is processed. - * Alternatively, we can wrap inserts to these tables into - * SET REFERENTIAL_INTEGRITY { TRUE | FALSE } calls. - */ - "CREATE TABLE DEFINERS(" // Included files defining required elements for a given compilation unit and project - "PID INTEGER, " // Project key (references PROJECTS) - "CUID INTEGER, " // Compilation unit key (references FILES) - "BASEFILEID INTEGER, " // File (often .c) requiring (using) a definition (references FILES) - "DEFINERID INTEGER" // File (often .h) providing a definition (references FILES) - //"FOREIGN KEY(PID) REFERENCES PROJECTS(PID), " - //"FOREIGN KEY(CUID) REFERENCES FILES(FID), " - //"FOREIGN KEY(BASEFILEID) REFERENCES FILES(FID), " - //"FOREIGN KEY(DEFINERID) REFERENCES FILES(FID)" - ");\n" - - "CREATE TABLE INCLUDERS(" // Included files including files for a given compilation unit and project - "PID INTEGER, " // Project key (references PROJECTS) - "CUID INTEGER, " // Compilation unit key (references FILES) - "BASEFILEID INTEGER, " // File included in the compilation (references FILES) - "INCLUDERID INTEGER" // Files that include it (references FILES) - //"FOREIGN KEY(PID) REFERENCES PROJECTS(PID), " - //"FOREIGN KEY(CUID) REFERENCES FILES(FID), " - //"FOREIGN KEY(BASEFILEID) REFERENCES FILES(FID), " - //"FOREIGN KEY(INCLUDERID) REFERENCES FILES(FID)" - ");\n" - - "CREATE TABLE PROVIDERS(" // Included files providing code or data for a given compilation unit and project - "PID INTEGER, " // Project key (references PROJECTS) - "CUID INTEGER, " // Compilation unit key (references FILES) - "PROVIDERID INTEGER" // Included file (references FILES) - //"FOREIGN KEY(PID) REFERENCES PROJECTS(PID), " - //"FOREIGN KEY(CUID) REFERENCES FILES(FID), " - //"FOREIGN KEY(PROVIDERID) REFERENCES FILES(FID)" - ");\n" - - "CREATE TABLE INCTRIGGERS(" // Tokens requiring file inclusion for a given compilation unit and project - "PID INTEGER, " // Project key (references PROJECTS) - "CUID INTEGER, " // Compilation unit key (references FILES) - "BASEFILEID INTEGER, " // File requiring a definition (references FILES) - "DEFINERID INTEGER, " // File providing a definition (references FILES) - "FOFFSET INTEGER, " // Definition's offset within the providing file - "LEN INTEGER" // Token's length - //"FOREIGN KEY(PID) REFERENCES PROJECTS(PID), " - //"FOREIGN KEY(CUID) REFERENCES FILES(FID), " - //"FOREIGN KEY(BASEFILEID) REFERENCES FILES(FID), " - //"FOREIGN KEY(DEFINERID) REFERENCES FILES(FID)" - ");\n" - - "CREATE TABLE FUNCTIONS(" // C functions and function-like macros - "ID " << db->ptrtype() << " PRIMARY KEY,\n" // Unique function identifier - "NAME " << db->varchar() << ",\n" // Function name (redundant; see FUNCTIONID) - "ISMACRO " << db->booltype() << ",\n" // True if a function-like macro (otherwise a C function) - "DEFINED " << db->booltype() << ",\n" // True if the function is defined within the workspace - "DECLARED " << db->booltype() << ",\n" // True if the function is declared within the workspace - "FILESCOPED " << db->booltype() << ",\n"// True if the function's scope is a single compilation unit (static or macro) - "FID INTEGER,\n" // File key of the function's definition, declaration, or use (references FILES) - "FOFFSET INTEGER,\n" // Offset of definition, declaration, or use within the file - "FANIN INTEGER,\n" // Fan-in (number of callers) - "FOREIGN KEY(FID) REFERENCES FILES(FID)\n" - ");\n" - - "CREATE TABLE FUNCTIONMETRICS(" // Metrics of defined functions and macros - "FUNCTIONID " << db->ptrtype() << " PRIMARY KEY,\n"; // Function identifier key (references FUNCTIONS) - // AUTOSCHEMA INCLUDE metrics.cpp Metrics - // AUTOSCHEMA INCLUDE funmetrics.cpp FunMetrics - for (int i = 0; i < FunMetrics::metric_max; i++) - if (!Metrics::is_internal(i)) - cout << Metrics::get_dbfield(i) << - (i >= FunMetrics::em_real_start ? " REAL" : " INTEGER") << - ",\n"; + // BEGIN AUTOSCHEMA + if (table_is_enabled(t_ids)) + cout << + "CREATE TABLE IDS(" // Details of interdependant identifiers appearing in the workspace + "EID " << db->ptrtype() << " PRIMARY KEY," // Unique identifier key + "NAME " << db->varchar() << "," // Identifier name + "READONLY " << db->booltype() << ", " // True if it appears in at least one read-only file + "UNDEFMACRO " << db->booltype() << ", " // True if it is apparantly an undefined macro + "MACRO " << db->booltype() << ", " // True if it a preprocessor macro + "MACROARG " << db->booltype() << ", " // True if it a preprocessor macro argument + "ORDINARY " << db->booltype() << ", " // True if it is an ordinary identifier (variable or function) + "SUETAG " << db->booltype() << ", " // True if it is a structure, union, or enumeration tag + "SUMEMBER " << db->booltype() << ", " // True if it is a structure or union member + "LABEL " << db->booltype() << ", " // True if it is a label + "TYPEDEF " << db->booltype() << ", " // True if it is a typedef + "ENUM " << db->booltype() << ", " // True if it is an enumeration member + "YACC " << db->booltype() << ", " // True if it is a yacc identifier + "FUN " << db->booltype() << ", " // True if it is a function name + "CSCOPE " << db->booltype() << ", " // True if its scope is a compilation unit + "LSCOPE " << db->booltype() << ", " // True if it has linkage scope + "UNUSED " << db->booltype() << // True if it is not used + ");\n"; + + if (table_is_enabled(t_files)) { + cout << + "CREATE TABLE FILES(" // File details + "FID INTEGER PRIMARY KEY," // Unique file key + "NAME " << db->varchar() << ",\n" // File name + "RO " << db->booltype(); // True if the file is read-only + // AUTOSCHEMA INCLUDE metrics.cpp Metrics + // AUTOSCHEMA INCLUDE filemetrics.cpp FileMetrics + for (int i = 0; i < FileMetrics::metric_max; i++) + if (!Metrics::is_internal(i)) + cout << ",\n" << Metrics::get_dbfield(i) << " INTEGER"; + cout << ");\n"; + } + + if (table_is_enabled(t_tokens)) + cout << + "CREATE TABLE TOKENS(" // Instances of identifier tokens within the source code + "FID INTEGER," // File key (references FILES) + "FOFFSET INTEGER," // Offset within the file + "EID " << db->ptrtype() << ",\n" // Identifier key (references IDS) + "PRIMARY KEY(FID, FOFFSET)," + "FOREIGN KEY(FID) REFERENCES FILES(FID)," + "FOREIGN KEY(EID) REFERENCES IDS(EID)" + ");\n"; + + if (table_is_enabled(t_comments)) + cout << + "CREATE TABLE COMMENTS(" // Comments in the code + "FID INTEGER," // File key (references FILES) + "FOFFSET INTEGER," // Offset within the file + "COMMENT " << db->varchar() << "," // The comment, including its delimiters + "PRIMARY KEY(FID, FOFFSET)," + "FOREIGN KEY(FID) REFERENCES FILES(FID)" + ");\n"; + + if (table_is_enabled(t_strings)) cout << - "FIDBEGIN INTEGER,\n" // File key of the function's definition begin (references FILES) - "FOFFSETBEGIN INTEGER,\n" // Offset of definition begin within the file - "FIDEND INTEGER,\n" // File key of the function's definition end (references FILES) - "FOFFSETEND INTEGER,\n" // Offset of definition end within the file - "FOREIGN KEY(FUNCTIONID) REFERENCES FUNCTIONS(ID)" - ");\n" - - "CREATE TABLE FUNCTIONID(" // Identifiers comprising a function's name - "FUNCTIONID " << db->ptrtype() << ", " // Function identifier key (references FUNCTIONS) - "ORDINAL INTEGER, " // Position of the identifier within the function name (0-based) - "EID " << db->ptrtype() << ", " // Identifier key (references IDS) - "PRIMARY KEY(FUNCTIONID, ORDINAL), " - "FOREIGN KEY(FUNCTIONID) REFERENCES FUNCTIONS(ID), " - "FOREIGN KEY(EID) REFERENCES IDS(EID)" - ");\n" - - "CREATE TABLE FCALLS(" // Function calls - "SOURCEID " << db->ptrtype() << ", " // Calling function identifier key (references FUNCTIONS) - "DESTID " << db->ptrtype() << ", " // Called function identifier key (references FUNCTIONS) - "FOREIGN KEY(SOURCEID) REFERENCES FUNCTIONS(ID), " - "FOREIGN KEY(DESTID) REFERENCES FUNCTIONS(ID)" - ");\n" - - "CREATE TABLE FILECOPIES(" // Files occuring in more than one copy - "GROUPID INTEGER, " // File group identifier - "FID INTEGER, " // Key of file belonging to a group of identical files (references FILES) - "PRIMARY KEY(GROUPID, FID), " - "FOREIGN KEY(FID) REFERENCES FILES(FID)" - ");\n" - - // END AUTOSCHEMA - ""; + "CREATE TABLE STRINGS(" // Strings in the code + "FID INTEGER," // File key (references FILES) + "FOFFSET INTEGER," // Offset within the file + "STRING " << db->varchar() << "," // The string, including its delimiters + "PRIMARY KEY(FID, FOFFSET)," + "FOREIGN KEY(FID) REFERENCES FILES(FID)" + ");\n"; + + if (table_is_enabled(t_rest)) + cout << + "CREATE TABLE REST(" // Remaining, non-identifier source code + "FID INTEGER," // File key (references FILES) + "FOFFSET INTEGER," // Offset within the file + "CODE " << db->varchar() << "," // The actual code + "PRIMARY KEY(FID, FOFFSET)," + "FOREIGN KEY(FID) REFERENCES FILES(FID)" + ");\n"; + + if (table_is_enabled(t_linepos)) + cout << + "CREATE TABLE LINEPOS(" // Line number offsets within each file + "FID INTEGER," // File key (references FILES) + "FOFFSET INTEGER," // Offset within the file + "LNUM INTEGER," // Line number (starts at 1) + "PRIMARY KEY(FID, FOFFSET)," + "FOREIGN KEY(FID) REFERENCES FILES(FID)" + ");\n"; + + + if (table_is_enabled(t_projects)) + cout << + "CREATE TABLE PROJECTS(" // Project details + "PID INTEGER PRIMARY KEY," // Unique project key + "NAME " << db->varchar() << // Project name + ");\n"; + + if (table_is_enabled(t_idproj)) + cout << + "CREATE TABLE IDPROJ(" // Identifiers appearing in projects + "EID " << db->ptrtype() << "," // Identifier key (references IDS) + "PID INTEGER," // Project key (references PROJECTS) + "FOREIGN KEY(EID) REFERENCES IDS(EID)," + "FOREIGN KEY(PID) REFERENCES PROJECTS(PID)" + ");\n"; + + if (table_is_enabled(t_fileproj)) + cout << + "CREATE TABLE FILEPROJ(" // Files used in projects + "FID INTEGER, " // File key (references FILES) + "PID INTEGER," // Project key (references PROJECTS) + "FOREIGN KEY(FID) REFERENCES FILES(FID)," + "FOREIGN KEY(PID) REFERENCES PROJECTS(PID)" + ");\n"; + + /* + * Foreign keys for the following four tables are not specified, because it is difficult + * to satisfy integrity constraints: files (esp. their metrics, esp. ncopies) can't + * be written until the end of processing, while to conserve space, these tables are + * written after each file is processed. + * Alternatively, we can wrap inserts to these tables into + * SET REFERENTIAL_INTEGRITY { TRUE | FALSE } calls. + */ + if (table_is_enabled(t_definers)) + cout << + "CREATE TABLE DEFINERS(" // Included files defining required elements for a given compilation unit and project + "PID INTEGER, " // Project key (references PROJECTS) + "CUID INTEGER, " // Compilation unit key (references FILES) + "BASEFILEID INTEGER, " // File (often .c) requiring (using) a definition (references FILES) + "DEFINERID INTEGER" // File (often .h) providing a definition (references FILES) + //"FOREIGN KEY(PID) REFERENCES PROJECTS(PID), " + //"FOREIGN KEY(CUID) REFERENCES FILES(FID), " + //"FOREIGN KEY(BASEFILEID) REFERENCES FILES(FID), " + //"FOREIGN KEY(DEFINERID) REFERENCES FILES(FID)" + ");\n"; + + if (table_is_enabled(t_includers)) + cout << + "CREATE TABLE INCLUDERS(" // Included files including files for a given compilation unit and project + "PID INTEGER, " // Project key (references PROJECTS) + "CUID INTEGER, " // Compilation unit key (references FILES) + "BASEFILEID INTEGER, " // File included in the compilation (references FILES) + "INCLUDERID INTEGER" // Files that include it (references FILES) + //"FOREIGN KEY(PID) REFERENCES PROJECTS(PID), " + //"FOREIGN KEY(CUID) REFERENCES FILES(FID), " + //"FOREIGN KEY(BASEFILEID) REFERENCES FILES(FID), " + //"FOREIGN KEY(INCLUDERID) REFERENCES FILES(FID)" + ");\n"; + + if (table_is_enabled(t_providers)) + cout << + "CREATE TABLE PROVIDERS(" // Included files providing code or data for a given compilation unit and project + "PID INTEGER, " // Project key (references PROJECTS) + "CUID INTEGER, " // Compilation unit key (references FILES) + "PROVIDERID INTEGER" // Included file (references FILES) + //"FOREIGN KEY(PID) REFERENCES PROJECTS(PID), " + //"FOREIGN KEY(CUID) REFERENCES FILES(FID), " + //"FOREIGN KEY(PROVIDERID) REFERENCES FILES(FID)" + ");\n"; + + if (table_is_enabled(t_inctriggers)) + cout << + "CREATE TABLE INCTRIGGERS(" // Tokens requiring file inclusion for a given compilation unit and project + "PID INTEGER, " // Project key (references PROJECTS) + "CUID INTEGER, " // Compilation unit key (references FILES) + "BASEFILEID INTEGER, " // File requiring a definition (references FILES) + "DEFINERID INTEGER, " // File providing a definition (references FILES) + "FOFFSET INTEGER, " // Definition's offset within the providing file + "LEN INTEGER" // Token's length + //"FOREIGN KEY(PID) REFERENCES PROJECTS(PID), " + //"FOREIGN KEY(CUID) REFERENCES FILES(FID), " + //"FOREIGN KEY(BASEFILEID) REFERENCES FILES(FID), " + //"FOREIGN KEY(DEFINERID) REFERENCES FILES(FID)" + ");\n"; + + if (table_is_enabled(t_functions)) + cout << + "CREATE TABLE FUNCTIONS(" // C functions and function-like macros + "ID " << db->ptrtype() << " PRIMARY KEY,\n" // Unique function identifier + "NAME " << db->varchar() << ",\n" // Function name (redundant; see FUNCTIONID) + "ISMACRO " << db->booltype() << ",\n" // True if a function-like macro (otherwise a C function) + "DEFINED " << db->booltype() << ",\n" // True if the function is defined within the workspace + "DECLARED " << db->booltype() << ",\n" // True if the function is declared within the workspace + "FILESCOPED " << db->booltype() << ",\n"// True if the function's scope is a single compilation unit (static or macro) + "FID INTEGER,\n" // File key of the function's definition, declaration, or use (references FILES) + "FOFFSET INTEGER,\n" // Offset of definition, declaration, or use within the file + "FANIN INTEGER,\n" // Fan-in (number of callers) + "FOREIGN KEY(FID) REFERENCES FILES(FID)\n" + ");\n"; + + if (table_is_enabled(t_functionmetrics)) { + cout << + "CREATE TABLE FUNCTIONMETRICS(" // Metrics of defined functions and macros + "FUNCTIONID " << db->ptrtype() << " PRIMARY KEY,\n"; // Function identifier key (references FUNCTIONS) + // AUTOSCHEMA INCLUDE metrics.cpp Metrics + // AUTOSCHEMA INCLUDE funmetrics.cpp FunMetrics + for (int i = 0; i < FunMetrics::metric_max; i++) + if (!Metrics::is_internal(i)) + cout << Metrics::get_dbfield(i) << + (i >= FunMetrics::em_real_start ? " REAL" : " INTEGER") << + ",\n"; + cout << + "FIDBEGIN INTEGER,\n" // File key of the function's definition begin (references FILES) + "FOFFSETBEGIN INTEGER,\n" // Offset of definition begin within the file + "FIDEND INTEGER,\n" // File key of the function's definition end (references FILES) + "FOFFSETEND INTEGER,\n" // Offset of definition end within the file + "FOREIGN KEY(FUNCTIONID) REFERENCES FUNCTIONS(ID)" + ");\n"; + + } + if (table_is_enabled(t_functionid)) + cout << + "CREATE TABLE FUNCTIONID(" // Identifiers comprising a function's name + "FUNCTIONID " << db->ptrtype() << ", " // Function identifier key (references FUNCTIONS) + "ORDINAL INTEGER, " // Position of the identifier within the function name (0-based) + "EID " << db->ptrtype() << ", " // Identifier key (references IDS) + "PRIMARY KEY(FUNCTIONID, ORDINAL), " + "FOREIGN KEY(FUNCTIONID) REFERENCES FUNCTIONS(ID), " + "FOREIGN KEY(EID) REFERENCES IDS(EID)" + ");\n"; + + if (table_is_enabled(t_fcalls)) + cout << + "CREATE TABLE FCALLS(" // Function calls + "SOURCEID " << db->ptrtype() << ", " // Calling function identifier key (references FUNCTIONS) + "DESTID " << db->ptrtype() << ", " // Called function identifier key (references FUNCTIONS) + "FOREIGN KEY(SOURCEID) REFERENCES FUNCTIONS(ID), " + "FOREIGN KEY(DESTID) REFERENCES FUNCTIONS(ID)" + ");\n"; + + if (table_is_enabled(t_filecopies)) + cout << + "CREATE TABLE FILECOPIES(" // Files occuring in more than one copy + "GROUPID INTEGER, " // File group identifier + "FID INTEGER, " // Key of file belonging to a group of identical files (references FILES) + "PRIMARY KEY(GROUPID, FID), " + "FOREIGN KEY(FID) REFERENCES FILES(FID)" + ");\n"; + + // END AUTOSCHEMA } void @@ -515,9 +618,10 @@ workdb_rest(Sql *db, ostream &of) // Project names const Project::proj_map_type &m = Project::get_project_map(); Project::proj_map_type::const_iterator pm; - for (pm = m.begin(); pm != m.end(); pm++) - cout << "INSERT INTO PROJECTS VALUES(" << - (*pm).second << ",'" << (*pm).first << "');\n"; + if (table_is_enabled(t_projects)) + for (pm = m.begin(); pm != m.end(); pm++) + cout << "INSERT INTO PROJECTS VALUES(" + << pm->second << ",'" << pm->first << "');\n"; vector files = Fileid::files(true); @@ -526,28 +630,33 @@ workdb_rest(Sql *db, ostream &of) // Details and contents of each file // As a side effect populate the EC identifier member for (vector ::iterator i = files.begin(); i != files.end(); i++) { - cout << "INSERT INTO FILES VALUES(" << - (*i).get_id() << ",'" << - (*i).get_path() << "'," << - db->boolval((*i).get_readonly()); - for (int j = 0; j < FileMetrics::metric_max; j++) - if (!Metrics::is_internal(j)) - cout << ',' << i->metrics().get_metric(j); - cout << ");\n"; + if (table_is_enabled(t_files)) { + cout << "INSERT INTO FILES VALUES(" + << i->get_id() << ",'" + << i->get_path() << "'," + << db->boolval(i->get_readonly()); + for (int j = 0; j < FileMetrics::metric_max; j++) + if (!Metrics::is_internal(j)) + cout << ',' << i->metrics().get_metric(j); + cout << ");\n"; + } // This invalidates the file's metrics - file_dump(db, cout, (*i)); + file_dump(db, cout, *i); // The projects this file belongs to for (unsigned j = attr_end; j < Attributes::get_num_attributes(); j++) - if ((*i).get_attribute(j)) - cout << "INSERT INTO FILEPROJ VALUES(" << - (*i).get_id() << ',' << j << ");\n"; + if (i->get_attribute(j) && table_is_enabled(t_fileproj)) + cout << "INSERT INTO FILEPROJ VALUES(" + << i->get_id() << ',' << j << ");\n"; // Copies of the file const set &copies(i->get_identical_files()); - if (copies.size() > 1 && copies.begin()->get_id() == i->get_id()) { + if (copies.size() > 1 + && table_is_enabled(t_filecopies) + && copies.begin()->get_id() == i->get_id()) { for (set ::const_iterator j = copies.begin(); j != copies.end(); j++) - cout << "INSERT INTO FILECOPIES VALUES(" << - groupnum << ',' << j->get_id() << ");\n"; + cout << "INSERT INTO FILECOPIES VALUES(" + << groupnum << ',' << j->get_id() + << ");\n"; groupnum++; } } diff --git a/src/workdb.h b/src/workdb.h index 9f941b99..3344e7c0 100644 --- a/src/workdb.h +++ b/src/workdb.h @@ -30,7 +30,40 @@ using namespace std; #include "sql.h" +// Keep this in sync with table_enable in workdb.cpp +enum e_table { + t_ids, + t_files, + t_tokens, + t_comments, + t_strings, + t_rest, + t_linepos, + t_projects, + t_idproj, + t_fileproj, + t_definers, + t_includers, + t_providers, + t_inctriggers, + t_functions, + t_functionmetrics, + t_functionid, + t_fcalls, + t_filecopies, + table_max +}; + +// Enable output of the specified table +void table_enable(const char *name); + +// Return true if the specified table is enabled +bool table_is_enabled(enum e_table t); + +// Output the database schema void workdb_schema(Sql *db, ostream &of); + +// Output database data void workdb_rest(Sql *db, ostream &of); #endif // WORKDB_