www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Generating table dependencies using templates

reply Aarti <aarti interia.pl> writes:
Hello!

In my program I need to generate dependencies between database tables, 
so I will always get information about below mentioned relations for 
every specific table:
1. parent tables
2. child tables
3. ancestor tables
4. descendant tables

To generate such a dependencies I have following matrix (table is much 
bigger in real program):

//tbl_vc,  tbl_ad,   tbl_dc, tbl_ic,  tbl_ct, tbl_root, tbl_end
const ubyte tablerel[tbl_end][tbl_end] = {
     {0,       1,        0,       1,      1,    	0}, //tbl_vc
     {0,       0,        1,       0,      0,    	0}, //tbl_ad
     {0,       0,        0,       0,      0,    	0}, //tbl_dc
     {0,       0,        0,       0,      0,    	0}, //tbl_ic
     {0,       0,        0,       0,      0,    	0}, //tbl_ct
     {1,       0,        0,       0,      0,    	0}, //tbl_root
};						    //tbl_end

Let's assume I want to find dependencies for table x:
- parents --> search x column and add to result every table from row 
label which on crossing with x column has 1 - e.g. parent of tbl_vc is 
tbl_root, parent for tbl_dc is tbl_ad
- children --> search x row and add to result every table from column 
label which on crossing with x row has 1 - e.g. children of tbl_vc are 
tbl_ad,  tbl_dt,  tbl_rlp,  tblrlo, tbl_ic,  tbl_ct,  tbl_dp,  tbl_ph, 
tbl_sn; for tbl_root the child is tbl_vc
- ancestor -> search for parents, add them to result and add also their 
parents
- descendants --> search for children, add them to result and add also 
their children

Now in C++ code I have two (at least these two I know) possibilities:
1. I can hardcode every relation in vector for every table, so I have:
int[] childrentables[tbl_end];

childrentables[tbl_vc][0]=tbl_ad; childrentables[tbl_vc][1]=tbl_ic; 
childrentables[tbl_vc][2]=tbl_ct;

childrentables[tbl_ad][0]=tbl_dc;
... much more definitions for every table ...

Now I make it with simple code generator, but this solution is very 
uncomfortable to use and difficult to modify when relations change.

2. I can generate these dependencies on runtime using recurence. This 
solution has runtime overhead and is more than I need as relations will 
never change on runtime.

I would be happy to find solution with D templates. Is it possible? How 
it should be implemented? Maybe you have some other suggestions?
I will appreciate your suggestions.

BR
Marcin Kuszczak
Apr 04 2006
next sibling parent Don Clugston <dac nospam.com.au> writes:
Aarti wrote:
 Hello!
 
 In my program I need to generate dependencies between database tables, 
 so I will always get information about below mentioned relations for 
 every specific table:
 1. parent tables
 2. child tables
 3. ancestor tables
 4. descendant tables
 
 To generate such a dependencies I have following matrix (table is much 
 bigger in real program):
 
 //tbl_vc,  tbl_ad,   tbl_dc, tbl_ic,  tbl_ct, tbl_root, tbl_end
 const ubyte tablerel[tbl_end][tbl_end] = {
     {0,       1,        0,       1,      1,        0}, //tbl_vc
     {0,       0,        1,       0,      0,        0}, //tbl_ad
     {0,       0,        0,       0,      0,        0}, //tbl_dc
     {0,       0,        0,       0,      0,        0}, //tbl_ic
     {0,       0,        0,       0,      0,        0}, //tbl_ct
     {1,       0,        0,       0,      0,        0}, //tbl_root
 };                            //tbl_end
 
 Let's assume I want to find dependencies for table x:
 - parents --> search x column and add to result every table from row 
 label which on crossing with x column has 1 - e.g. parent of tbl_vc is 
 tbl_root, parent for tbl_dc is tbl_ad
 - children --> search x row and add to result every table from column 
 label which on crossing with x row has 1 - e.g. children of tbl_vc are 
 tbl_ad,  tbl_dt,  tbl_rlp,  tblrlo, tbl_ic,  tbl_ct,  tbl_dp,  tbl_ph, 
 tbl_sn; for tbl_root the child is tbl_vc
 - ancestor -> search for parents, add them to result and add also their 
 parents
 - descendants --> search for children, add them to result and add also 
 their children
 
 Now in C++ code I have two (at least these two I know) possibilities:
 1. I can hardcode every relation in vector for every table, so I have:
 int[] childrentables[tbl_end];
 
 childrentables[tbl_vc][0]=tbl_ad; childrentables[tbl_vc][1]=tbl_ic; 
 childrentables[tbl_vc][2]=tbl_ct;
 
 childrentables[tbl_ad][0]=tbl_dc;
 ... much more definitions for every table ...
 
 Now I make it with simple code generator, but this solution is very 
 uncomfortable to use and difficult to modify when relations change.
 
 2. I can generate these dependencies on runtime using recurence. This 
 solution has runtime overhead and is more than I need as relations will 
 never change on runtime.
 
 I would be happy to find solution with D templates. Is it possible? How 
 it should be implemented? Maybe you have some other suggestions?
 I will appreciate your suggestions.

It's hard without array literals, but you could do it with a const string. Untested, but I've done this sort of thing before... const int numTables = 6; const char [] tableDependencies = "010110" "001000" "000000" ...; static assert(tableDependencies.length == numTables*numTables); // true if dependencies[x][y] is '1'. template dependsOn(int x, int y) { const bool dependsOn = (tableDependencies[x*numTables+y]=='1'; } // Returns an array of all the parents of table x. // A bit of a hack -- we can concat char [] at compile time, // but not const int[]. // int [] parentsOf!(x). template parentsOf(int x, int row=0, dchar [] sofar="") { static if (row==numTables) const int [] parentsOf = cast(int [])(sofar); else static if (dependsOn(x, row)) const int [] parentsOf = parentsOf(x, row+1, sofar~cast(dchar)(row)); else const int [] parentsOf = parentsOf(x, row+1, sofar); } // Usage: const int tbl_vc = 1; ... etc. int [] p = parentsOf!(tbl_vc);
Apr 04 2006
prev sibling parent Georg Wrede <georg.wrede nospam.org> writes:
Aarti wrote:
 Hello!
 
 In my program I need to generate dependencies between database tables, 
 so I will always get information about below mentioned relations for 
 every specific table:
 1. parent tables
 2. child tables
 3. ancestor tables
 4. descendant tables

I'm not sure whether this is posted in order to find a solution for the problem, or to find information on best practices with templates. Since Don already started to tackle the latter, I'll merely mention how I'd resolve the former. In general, with database tables and this kind of problem, I'd resort to recursive lookups. I'd have an extra table that contains the fields TABLE, ANCESTOR. (If there is a huge number of tables, then of course one could have this table indexed on both columns, but in practice neither index is needed because in real-life applications the total number of tables is "small".) To find out whether table A is an ancestor to table B, one calls a function that checks for all "parents" to table B, and if A is found, then return A. If parents are found but not A, then check their parents. Conversely if one needs to know if A is a descendant.
Apr 04 2006