/*
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);
}