RJLRef: $PH/06f522/asgnt3/CKquery_chgenUseTutorial.txt Response to A Miles inputs on keyExists notes from kb : > From alison_lea@yahoo.com Thu Oct 12 18:24:04 2006 > From: Alison Miles > Subject: Re: 91.522 HW3 - keyExists (kb: discussion group,generics) > To: Nitin Sonawane , > Keith Bagley > Cc: 06f522 > > Notes: > > Got chgen checked out successfully. I haven't tried > to build anything, though. > > Below is some pseudocode. I don't think I'm going in > the right direction here...I was trying to modify the > pseudo code to use Nitin's functions but I think there > are things I'm missing and functions I could use that > I'm not. > > > The idea was: > > We're supplied a tableType, a CKname, and a value list > of the format "91 522 291". > > I wanted to find the TT row where the CKname was RJL>>>[All refs to pr_*.c files below are to the version in $PH/06f522/asgnt3/lechner/metatest2/src These files are produced by my Makefile that runs chgen13 on metaschemaCK.sch and compiles metatest2.exe.] If you set TTcurr = CAcurr->TAid_pp->TTid_pp, then strcmp(TTcurr->ttype, tableType) == zero (equality). In general CAcurr->TAid_pp->TTid_pp might be some container table type (a composite aggregation - Larman: 16.13 p. 264). Assert(strcmp(CKcurr->TTid_pp->ttype, #tableType)==0) to verify that tblType is the ttype in CK's parent TT. > defined and examine all of > the CK's (with that TT as an fkey) to compare their CA > values against valueList components. I don't think I I think you want to search the table iin the app DB whose format is declared by the TA-children of the TT at CKcurr->TTid_pp which is parent to the given CK-rowi. Remember, CK's define candidate leys for an app DB table. The corresponding TT_row is metadata which only defines the FORMAT of that app table, including its TTcurr->ttabb table type mnemonic (e.g. AA, RT, CO, CD, if the app schema is $PH/COOL-GEN/SISrev061011.sch[.txt]]) Search table CK for CKname to find the CK which declares (via CK to CA to TA) the field name list. Since CKname is not a pkey, use find_str_loop(viewname,tbl,field,value): i.e. find_str_loop("metaviewCK". CK, CKname, CKname); (first CKname is a CK-datamember NAME; 2nd CKname is the char* string VALUE to be searched for) Then each key-field's ftype, fname or is_key is referenced at CAcurr->TAid_pp->{ftype,fname.is_key} (choose one) inside child_loop(CK,CA,CAid,CKid). More conservatively (but slower), encapsulate the access: E.g. to get the TA's fname string use: TableAttributeGetffname(CAcurr->TAid)) (Assuming pr_accessors.c is generated from $PH/06f522/asgnt3/lechner/metatest2/metaschemaCK.sch.) BTWay, you call pr_parse like this: ( at $PH/06f522/asgnt3/lechner/metatest2/src/pr_load.c:1641:) pr_parse(viewname, hcg_buffer, tbl_encoding, idx, hcg_k); A 'real' database is loaded by pr_load() which opens the input file, calls load_data(char *viewname) and closes the file. load_data (at pr_load.c:1526:) calls pr_parse and pr_link on each valid database table row it reads from its input datafile. The definition of pr_parse begins like this: (at pr_load.c:1675:) -------------------------- void pr_parse (char viewname[], char buffer[], int tbl_encoding, int idx, hcg_key hcg_k) { dprints("Row to be added = %s\n", buffer); switch( tbl_encoding ) { case 0 : /* encoding of SV */ SVelt = pr_create(SV); SVelt->SVid = hcg_k; hcg_parse(buffer,hcg_t,&idx); mystrcpy(SVelt->PVid,hcg_t,8,0); hcg_parse(buffer,hcg_t,&idx); mystrcpy(SVelt->svname,hcg_t,30,1); hcg_parse(buffer,hcg_t,&idx); mystrcpy(SVelt->sformat,hcg_t,6,0); hcg_parse(buffer,hcg_t,&idx); mystrcpy(SVelt->sversion,hcg_t,12,1); hcg_parse(buffer,hcg_t,&idx); pr_set_int(SVelt,lastMod,atoi(hcg_t)); hcg_parse(buffer,hcg_t,&idx); mystrcpy(SVelt->svpath,hcg_t,80,0); mystrcpy(SVelt->descr,buffer+idx,80,1); break; case 1 : /* encoding of TT */ ... } // end pr_parse --------------------------- As shown, pr_parse will look at the pkey's table type (tbl_encoding and idx) and perform its corresponding case: pr_create just allocates enough memory for the table-row, and hcg_parse extracts each string value to a string buffer. Then pr_set_ converts it (or mystrcpy copies it) into a field in the object. [TBD: refactor pr_set_* into TablenameSetFieldname(pkey, value);] Note: this object is not yet inserted in the database, (fortuntely) but it can be used as a value list for fields of a CQ (candidate key value query) instance. [In load_data,] after a text-formatted record is converted into an object by pr_parse, pr_link (pr_load.c:1249:) is called to insert the new object into each of its linked lists. Loading a datafile is not the only way to insert new table rows. Any GUI process to create new objects can get values in non-ASCII format and insert them directly into a (struct XX) type. E.g., bde/src contains 70 refs to pr_add, while its pr_util_nolog contains no refs ouside of comments. (bde/src/*ops.cc 'Create' operations all call pr_add; pr_add calls do_pr_add, which calls pr_link but not pr_parse. An interactive CK-query acquisition process could do the same.) My metatest2Main.c driver calls pr_load to initalize its school database. [So far, it only tries to load metaschemaCK.msdat.] My metatest2main.c doesn't create any new objects after pr_loading its databse, so it doesn't call pr_add. I expect to add test data table types to $PH/COOL-GEN/SISrev061010.sch I will append $PH/COOL-GEN/SISrev061010.sch to metatest2/metaschemaCK.sch, renaming it SISrev06101x.sch. Then CK-test query table rows can also be pr_loaded and passed to unit-test procedures called from metatest2Main.c Another way to add table rows is by calling pr_add. The macro pr_add at metaschemaCK.h exists for application programmers. (It is referenced 70 times in $RBGB/src/*.cc). Its purpose is merely to 'stringize' the table abbrev in arg2 of do_pr_add (pr_load.c:1397:) #define pr_add(a,b,c) do_pr_add(a,#b,c) do_pr_add calls pr_gen_pkey which commits and installs the primary key field, and a sequence of macro calls to pr_check_str at pr_load.c:1374 which "sets the default value of non-key fields" (string values), followed by a call to pr_link(tbl_encoding) (using tbl_ptr). The definition of do_pr_add begins this way: ----------------------------- void do_pr_add (char *viewname, char *tbl_abbrv, hcg_ptr tbl_ptr) { char error_table[HCG_ABBR_SIZE+1]; /*char tempkey[HCG_KEY_SIZE+1];*/ int tbl_encoding; // check for valid argument values . . . tbl_encoding = encoding( hcg_table_seq_list[hcg_tbl_idx].ttabbrev ); switch( tbl_encoding ) { case 0 : /* encoding of SV */ SVelt = (struct SV *) tbl_ptr; pr_gen_pkey(viewname,SV,SVelt->SVid); pr_check_str (SV,SVelt,PVid,8); pr_check_str (SV,SVelt,svname,30); pr_check_str (SV,SVelt,sformat,6); pr_check_str (SV,SVelt,sversion,12); pr_check_str (SV,SVelt,svpath,80); pr_check_str (SV,SVelt,descr,80); pr_link(tbl_encoding); break; case 1 : /* encoding of TT */ . . . ---------------------------- pr_check_str makes sure that string fields are padded (or truncated) to fit within their allocated space in the object. (Text fields are char[] not char*). If this seems complicated, it is. But remember this is automatically generated code. Someone has to test it a lot, before you can trust it like you trust your compiler.:-) Bob Lechner =============================================== > did that. When I got done removing the > things that didn't look great, I realized that this > was basically Chris's prototype with a new function > call thrown in but I wanted to throw it out here > anyway. I'm looking at this further and will keep > everyone updated. > > > boolean ckeyValueListExists( > char* tableType, /* a TTabbrev--is this the TTid?*/ > char* CKname, /* a CK name */ > char* valueList) /* CK values--string */ > { > char **vals; > struct TA **att_ptrs; > int num_attribs; > int ttid, ckid; > int good; > > > // get strings for each attrib value > vals = value_parse(valueList, &num_attribs); > > // Return an array of attribute structs. Their > types are determined > by > // CKname. > att_ptrs = ckey_parse(CKname, &num_attribs); > > // updates TTcurr. > pr_find_str(TT, tableType, "CK"); > encode(TTcurr->ttid, &ttid); > > // Somehow...child_loop? > foreach(CK of TT) > { > // same type of CK > if (!strcmp(CKcurrname, CKName)) > { > good = TRUE; > > // get TAs of this CK > attr_ptrs2 = ckey_parse(CKcurr, &num_attribs); > for (i = 0; i < num_attribs; i++) > { > // here's the real pseudo stuff > compare attr_ptrs2[i] value against vals[i]; > > } > if we got a match of all attrib values, > return(TRUE); > } > } > return(FALSE); > > }