/* dolemite Copyright (C) 2000 Kyle Cronan, Gus Huber This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA The dolemite home page is at http://dolemite.pbx.org Please send bug reports and other feedback to: -------------------------------------------------------------------------- guile db field fetching functions */ #include #include #include #include #include #define MAX_DEPTH 6 struct link { int id; char *clause; }; struct link customer_links[] = { /* link w/ accounts */ { 1, "customers.id=accounts.customerid", }, /* link w/ customerplans */ { 2, "customers.id=customerplans.customerid", }, /* link w/ calls */ { 4, "customers.id=calls.customerid", }, /* link w/ resellers */ { 7, "customers.resellerid=resellers.id", }, /* link w/ admedias */ { 10, "customers.admediaid=admedias.id", }, { -1, NULL, }, }; struct link account_links[] = { /* link w/ customers */ { 0, "accounts.customerid=customers.id", }, /* link w/ customerplans */ { 2, "accounts.id=customerplans.accountid", }, /* link w/ transactions */ { 3, "accounts.id=transactions.accountid", }, /* link w/ calls */ { 4, "accounts.id=calls.accountid", }, /* link w/ transactiontypes */ { 11, "accounts.transactiontypeid=transactiontypes.id", }, { -1, NULL, }, }; struct link customerplan_links[] = { /* link w/ customers */ { 0, "customerplans.customerid=customers.id", }, /* link w/ accounts */ { 1, "customerplans.accountid=accounts.id", }, /* link w/ plans */ { 5, "accounts.planid=plans.id", }, { -1, NULL, }, }; struct link transaction_links[] = { /* link w/ accounts */ { 1, "transactions.accountid=accounts.id", }, /* link w/ resellers */ { 7, "transactions.resellerid=resellers.id", }, /* link w/ transactiontypes */ { 11, "transactions.transactiontypeid=transactiontypes.id", }, { -1, NULL, }, }; struct link call_links[] = { /* link w/ customers */ { 0, "calls.customerid=customers.id", }, /* link w/ accounts */ { 1, "calls.accountid=accounts.id", }, { -1, NULL, }, }; struct link plan_links[] = { /* link w/ customerplans */ { 2, "plans.id=customerplans.planid", }, { -1, NULL, }, }; struct link resellersite_links[] = { /* link w/ resellers */ { 7, "resellersites.resellerid=resellers.id", }, { -1, NULL, }, }; struct link reseller_links[] = { /* link w/ customers */ { 0, "resellers.id=customers.resellerid", }, /* link w/ transactions */ { 3, "resellers.id=transactions.resellerid", }, /* link w/ resellersites */ { 6, "resellers.id=resellersites.resellerid", }, /* link w/ ratetables */ { 8, "resellers.id=ratetables.resellerid", }, { -1, NULL, }, }; struct link ratetable_links[] = { /* link w/ resellers */ { 7, "ratetables.resellerid=resellers.id", }, /* link w/ rates */ { 9, "ratetables.id=rates.ratetableid", }, { -1, NULL, }, }; struct link rate_links[] = { /* link w/ ratetables */ { 8, "rates.ratetableid=ratetables.id", }, { -1, NULL, }, }; struct link admedia_links[] = { /* link w/ customers */ { 0, "admedias.id=customers.admediaid", }, { -1, NULL, }, }; struct link transactiontype_links[] = { /* link w/ accounts */ { 1, "transactiontypes.id=accounts.transactiontypeid", }, /* link w/ transactions */ { 3, "transactiontypes.id=transactions.transactiontypeid", }, { -1, NULL, }, }; struct table { char *name; struct link *links; } topology[] = { /* Customers table, id 0 */ {"customers", NULL}, /* Accounts table, id 1 */ {"accounts", NULL}, /* Customerplans table, id 2 */ {"customerplans", NULL}, /* Transactions table, id 3 */ {"transactions", NULL}, /* Calls table, id 4 */ {"calls", NULL}, /* Plans table, id 5 */ {"plans", NULL}, /* Reseller Sites table, id 6 */ {"resellersites", NULL}, /* Resellers table, id 7 */ {"resellers", NULL}, /* Rate Tables table, id 8 */ {"ratetables", NULL}, /* Rates table, id 9 */ {"rates", NULL}, /* Admedias table, id 10 */ {"admedias", NULL}, /* Transaction Types table, id 11 */ {"transactiontypes", NULL}, {NULL, NULL}, }; void complete_topology(struct table *top) { top[0].links=customer_links; top[1].links=account_links; top[2].links=customerplan_links; top[3].links=transaction_links; top[4].links=call_links; top[5].links=plan_links; top[6].links=resellersite_links; top[7].links=reseller_links; top[8].links=ratetable_links; top[9].links=rate_links; top[10].links=admedia_links; top[11].links=transactiontype_links; } struct node { int id; struct node *next; }; struct node *find_path(struct table *top, int src, int dst, int depth) { int i; struct node *ret, *nxt; if (src==dst) return NULL; printf("find_path %d -> %d (max - depth %d)\n", src, dst, depth); for (i=0;top[src].links[i].clause;i++) if (top[src].links[i].id==dst) { ret=(struct node *)malloc(sizeof(struct node)); nxt=(struct node *)malloc(sizeof(struct node)); nxt->id=dst; nxt->next=NULL; ret->id=src; ret->next=nxt; return ret; } if (!depth) return NULL; for (i=0;top[src].links[i].clause;i++) if ((nxt=find_path(top, top[src].links[i].id, dst, depth-1))) { ret=(struct node *)malloc(sizeof(struct node)); ret->id=src; ret->next=nxt; return ret; } return NULL; } struct node *walk_topology(char **names, int n) { int i, j, k=0, *t; struct table *top=topology; struct node *path, *cur, *cur2, *cur3, *ret=NULL; t=(int *)malloc(sizeof(int)*(n+1)); for (i=0;names[i];i++) for (j=0;top[j].name;j++) if (!strcasecmp(top[j].name, names[i])) t[k++]=j; for (i=0;inext) printf("%s, ", top[cur->id].name); printf(") found from node %d to node %d\n", t[i], t[i+1]); if (!ret) ret=path; else { for (cur=ret;cur->next;cur=cur->next); cur->next=path; } } /* remove duplicates */ for (cur=ret;cur;cur=cur->next) for (cur2=ret,cur3=NULL;cur2 && cur2!=cur;cur3=cur2, cur2=cur2->next) if (cur->id==cur2->id) { cur3->next=cur2->next; free(cur2); } printf("Final path: ( "); for (cur=ret;cur;cur=cur->next) printf("%s, ", top[cur->id].name); printf(")\n"); free(t); return ret; } int construct_query(char **f, char **c, char **p) { int i, j, k=0, l, m=0, n; char **t, *s; struct node *path, *cur, *rem; /* printf("fields:\n"); for (i=0;f[i];i++) printf(" %s\n", f[i]); printf("constraints:\n"); for (i=0;c[i];i++) printf(" %s\n", c[i]); printf("parameters:\n"); for (i=0;p[i];i++) printf(" %s\n", p[i]); */ for (n=0,i=0;f[i];i++) for (j=0;f[i][j];j++) if (f[i][j]=='.') n++; t=(char **)malloc(sizeof(char *)*(n+1)); for (i=0;f[i];i++) for (j=0;f[i][j];j++) if (f[i][j]=='.') { for (k=j-1,l=j-1;f[i][k] && isalnum(f[i][k]);k--); s=(char *)malloc(sizeof(char)*(l-k+1)); strncpy(s, &f[i][k+1], l-k); s[l-k]='\0'; t[m++]=s; } t[m]=NULL; if (n) path=walk_topology(t, n); for (cur=path;cur;) { rem=cur; cur=cur->next; free(rem); } free(t); return 1; } SCM db_get(SCM fields, SCM constraints, SCM params) { int i=0, len=0; SCM mem, str; char **f, **c=NULL, **p=NULL; /* Thanks to Jorgen 'Forcer' Schaefer for the following code: */ if (gh_null_p(fields)) scm_wrong_num_args(gh_str02scm("db-get")); for (mem=fields;!SCM_NULLP(mem);mem=SCM_CDR(mem)) { SCM_ASSERT(SCM_CONSP(mem), fields, SCM_ARG1, "db-get"); str=SCM_CAR(mem); SCM_ASSERT(SCM_NIMP(str) && SCM_ROSTRINGP(str), fields, SCM_ARG1, "db-get"); len++; } f=(char **)malloc(sizeof(char *)*(len+1)); for (mem=fields;!SCM_NULLP(mem);mem=SCM_CDR(mem)) { str=SCM_CAR(mem); f[i++]=SCM_ROCHARS(str); } f[i]=NULL; len=0; i=0; if (constraints!=SCM_UNDEFINED && !gh_null_p(constraints)) { for (mem=constraints;!SCM_NULLP(mem);mem=SCM_CDR(mem)) { SCM_ASSERT(SCM_CONSP(mem), constraints, SCM_ARG2, "db-get"); str=SCM_CAR(mem); SCM_ASSERT(SCM_NIMP(str) && SCM_ROSTRINGP(str), constraints, SCM_ARG2, "db-get"); len++; } c=(char **)malloc(sizeof(char *)*(len+1)); for (mem=constraints;!SCM_NULLP(mem);mem=SCM_CDR(mem)) { str=SCM_CAR(mem); c[i++]=SCM_ROCHARS(str); } c[i]=NULL; } len=0; i=0; if (params!=SCM_UNDEFINED && !gh_null_p(params)) { for (mem=params;!SCM_NULLP(mem);mem=SCM_CDR(mem)) { SCM_ASSERT(SCM_CONSP(mem), params, SCM_ARG3, "db-get"); str=SCM_CAR(mem); SCM_ASSERT(SCM_NIMP(str) && SCM_ROSTRINGP(str), params, SCM_ARG3, "db-get"); len++; } p=(char **)malloc(sizeof(char *)*(len+1)); for (mem=params;!SCM_NULLP(mem);mem=SCM_CDR(mem)) { str=SCM_CAR(mem); p[i++]=SCM_ROCHARS(str); } p[i]=NULL; } construct_query(f, c, p); free(f); free(c); free(p); return SCM_BOOL_T; } void main_proc(int argc, char *argv[]) { char input_str[200]; gh_new_procedure("db-get", (SCM (*)())db_get, 1, 2, 0); fputs("bleh> ", stdout); while (fgets(input_str, 199, stdin) != NULL) { gh_eval_str(input_str); fputs("\nbleh> ", stdout); } exit(0); } int main(int argc, char *argv[]) { char *bleh[]={"plans.bleh", "rates.bleh"}; complete_topology(topology); /* while (1) { construct_query(bleh, NULL, NULL); usleep(10000); }; */ gh_enter(argc, argv, main_proc); }