As I said earlier, table CQ is NOT necessary. However this confuses me: > - would the CQ table also contain values? because: if it did not contain values, then how could it be [a unit test for] a query? The OPTIONAL part of such a query (instance) would be the fieldNAME list. (It is mandatory only in naive XML.) But I do NOT know what Nitin means by 'string representation of candidate keys': (query test instances, or specs? field Values or field Names?). FNames are already present in the CK---->CA aggregate after pr_loading (pr_parse-ing) the CK input specifications. CQ (instance) strings with a list (repeating group) of field values are analogous to CK-specs with multiple fnames, instead of a CK-row plus multiple CA-child rows. I had hoped you would see the analogy and reuse [the same] pr_add/pr_parse/pr_link methods for both. The CK--->CA CandidateKey to fieldnamelist aggregation suggests an analogous CT--->CV table key to field values aggregation, where CT contains the CKname and TTid fields of CQ and each CV child of CT contains one field value. Pr_loading CK--->CA SPEC content is justified by its stability as metadata and reusability as GU methods. Code for keyExists methods can be based on this metadata, (either as hand-written or auto-generated code for compilation, or as [meta-]data for which you write a generic table-driven interpreter like LCP. Pr_loading all CQ--->CV unit TEST data can only be justified if it is convenient. It is NOT convenient for asgnt3. However, automated regression testing requires a database of test cases (inputs paired with expected outcomes). Regrssion tests are repeated after each build, to verify that earlier successful tests do not now fail, or to isolate a new bug to the latest code change. This test database grows because new unit test cases are added to keep pace to the growing functionality of the code base. That was my point in giving you a heads-up. My compromise for loading query instance data is to define one CQ-row as the join of CKname to [a string containing] all of its field value instances. From CKname we can get the CKrow and its CKcurr and TTId_pp. Freading this CQ-row to a buffer and splitting it up is what's inside the existing pr_load/load_data read loop: For each CQ-row, pr_parse converts the ASCII field values to a row-instance of type struct CV (pr_link is not needed unless we associate CQ input data with expected output data (Query Result QR?). (If some tests do not have QR results, CQ to QR would be a 1..1 to 0..1 association.) CQ conversion does atoi, encode, or strncmp depending on field type. CK would have to be subclassed (or templatized) not only on the TT-parent type but ALSO on the CKname. AFAIK, the latter is possible only at UNreasonable complexity. This dependence on named field types precludes using the Visitor Design Pattern (which depends on the entity type it visits to choose a conversion method). Making each CK-spec (CK-row instance) a new entity class would also lead to subclass proliferation. I conclude that each field value conversion (to take advantage of CK--->CA>--TA metadata) must be inside a switch(field_type) with cases {int, hcg_key, char*} to convert a CA-child's field value. This is not generated by chgen, just as a test for object (or CK-field-list) equality is not generated by chgen. Therefore pr_load from chgen can only read and split the field value list (via hcg_parse). YOUR CODE must complete the task by converting each field value of a CQ. BUT: an extension to chgen MIGHT be able to do this: Right now it only converts a schema-specified list of field values for any table type XX, because chgen generates code within a switch(ttidx) case block for a given declared table type. This case block for any table type XX can be refactored into a class-specific XXelt->load_row method and call. Gencpp already does this refactoring and its mehod can probably replace chgen's. REF: A gencpp test for the DEpt-->COurse==>PQ (PreRequisite) subschema, $CASE/gen/gencpp/ver_1/test/test_co_pr.sch, is at this path: ----------------------------- mercury(17)> pwd /nfs/galaxy/misc/proj3/case/gen/gencpp/ver_1/test mercury(19)> wc *.h *.cc 134 566 5337 COschema.h 109 458 4292 DEschema.h 100 413 3739 EMschema.h 100 419 3781 ONschema.h 132 541 4799 PRschema.h 1650 7042 69699 test_co_pr.h 511 1374 15117 COops.cc 419 1196 12918 DEops.cc 382 1144 12242 EMops.cc 382 1144 12245 ONops.cc 34 116 1335 pr_delete.cc 97 301 3148 pr_dump.cc 42 101 1267 pr_free.cc 2059 6221 61052 pr_load.cc 492 1396 15275 PRops.cc 97 327 4046 pr_stats.cc 256 604 7163 test_co_pr.cc 6996 23363 237455 total mercury(20)> ----------------- For example, compare the USE_STL and non-STL alternate versions of load_data in pr_load.cc below, after fopen, fread loop entry and table-type encoding: Witbout USE_STL, chgen-style code is generated: pr_parse and pr_link each repeat switch(tbl_encoding) inside of which they call gencpp's new refactored table-specific parse_row and link_row methods. With USE_STL, there is only one switch(tbl_encoding) whose case blocks call both of the class-specific overrides to parse_row (construct) and pr_link (link-in) the table row. (At least one switch(tbl_encoding) is unavoidable to identify the entity class or table-row type from a persistent database which is a union of schema-defned table types.) Sample parse_row and link_row methods are also shown for class CO (in a schema much simpler than SISrev0561014.sch). They call the same masros that chgen defines (for compatibility- afer all, gencpp is supposed to be an incremental refactoring of chgen. What gencpp does NOT do is hybridize VMNetDB: i.e., use a Vector container (as when USE_STL is #defined) to contain all rows of a table, but use intrusive linked lists (like chgen) (as when USE_STL is NOT #defined) for each parent-child relationship. This would avoid gencpp's current proliferation of instantiating and overhead of maintaining a distinct STL container for every parent-row-instance when USE_STL is #defined. TBD: Possible projects: (1) Refactor gencpp to hybridize its output code, and remove the conditional compilation dependency on USE_STL. (2) Refactor bde/src to use this hybrid version of gencpp output code. (This would be simpler than refactoring bde for the current USE_STL code, although more complex than refactoring bde to use gencpp's output API when USE_STL is NOT #defined.) ----------------- //extract fron pr_load.cc: #ifndef USE_STL /* 93su523 PGEN merge (BEGIN) */ tbl_encoding = encoding( hcg_table_seq_list[hcg_tbl_idx].ttabbrev ); pr_parse(viewname, hcg_buffer, tbl_encoding, idx, hcg_k); pr_link( tbl_encoding ); /* 93su523 PGEN merge (END) */ #else tbl_encoding = encoding( hcg_table_seq_list[hcg_tbl_idx].ttabbrev ); /* This code is from pr_parse, and it calls XXrow's constructor */ switch( tbl_encoding ) { case 0 : /* encoding of EM */ EM *EMnewRow; EMnewRow = new EM; EMnewRow->parse_row(hcg_buffer, idx, hcg_k); EMnewRow->link_row(); break; case 1 : /* encoding of ON */ ON *ONnewRow; ONnewRow = new ON; ONnewRow->parse_row(hcg_buffer, idx, hcg_k); ONnewRow->link_row(); break; case 2 : /* encoding of DE */ DE *DEnewRow; DEnewRow = new DE; DEnewRow->parse_row(hcg_buffer, idx, hcg_k); DEnewRow->link_row(); break; case 3 : /* encoding of CO */ CO *COnewRow; COnewRow = new CO; COnewRow->parse_row(hcg_buffer, idx, hcg_k); COnewRow->link_row(); break; case 4 : /* encoding of PR */ PR *PRnewRow; PRnewRow = new PR; PRnewRow->parse_row(hcg_buffer, idx, hcg_k); PRnewRow->link_row(); break; } #endif /* USE_STL */ hcg_read_next(); } // end switch } // end load_data ---------------------- //extracts from COops.cc: (code for parse_row and link_row mehods) void CO::parse_row (char *buffer, int idx, hcg_key hcg_k) { #ifdef USE_STL set_pkid(hcg_k); #else RC::set_pkid(hcg_k); #endif hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); DEid = hcg_k; mystrcpy(name,buffer+idx,15,0); } ------------------------ void CO::link_row() { hcg_key COid; #ifndef USE_STL insert_element(CO); #else COtab->insertRow(this); #endif /* USE_STL */ link_child_bp_m(PR,CO,COid1,COid,COid1,PRid1); link_child_bp_m(PR,CO,COid2,COid,COid2,PRid2); link_parent_bp_m(CO,DE,DEid,DEid,DEid,COid); } ---------------------------- > From nitin.sonawane@gmail.com Sun Oct 22 10:09:12 2006 > From: "Nitin Sonawane" > To: "Bob Lechner" , "Alison Miles" , > Prof Lechner, > > I was wondering if we really need a query table "CQ" for assignment three. > So far, I have been assuming that we can have a simple ad-hoc querying > mechanism driven by two strings ckName & valueList passed to the proposed > keyExists() function. > > Perhaps it is clear to other classmates how we would use the CQ table, it is > not very clear to me. > - would the CQ table simply contain a string representation of candidate > keys? > - would the CQ table also contain values? > > Any advise would be appreciated. I have some start on the test driver and > would like to make progress this weekend. > > Thanks, > Nitin. >