/* Subject: Re: Sybase module -- input sought From: jredford@lehman.com To: ags@uncompaghre.informatics.jax.org (Alexander G. Smith) Cc: python-list@cwi.nl Date: Tue, 10 May 94 11:53:13 -0400 input sought? how about a complete module? :) This is a fairly incomplete work.. but I have done things dramatically differently than sybperl would. Given the nature of the language I find it is easier to simply get ALL results & then muck with the rows later as parts of the data. This is a subset of the functionality of a Modula-3 interface to Sybase that I wrote.. I could send you that if you are interested in a more complete picture. */ #include #include #include #include "allobjects.h" #include "modsupport.h" static object *SybaseError; /* exception sybase.error */ typedef struct { OB_HEAD LOGINREC *login; /* login record */ DBPROCESS *dbproc; /* login record */ } sybdbobject; extern typeobject SybDbtype; /* Forward */ static sybdbobject * newsybdbobject(char *user, char *passwd, char *server) { sybdbobject *s; s = NEWOBJ(sybdbobject, &SybDbtype); if (s != NULL) { s->login = dblogin(); if (user) { (void)DBSETLUSER(s->login, user); } if (passwd) { (void)DBSETLPWD(s->login, passwd); } if(!(s->dbproc = dbopen(s->login, server))) { dbloginfree(s->login); DEL(s); return (NULL); } } return s; } /* OBJECT FUNCTIONS: sybdb */ /* Common code for returning pending results */ static object *getresults (DBPROCESS *dbp) { object *results; object *list; object *tuple; object *o; int retcode; int cols; int *fmt; int i; results = newlistobject(0); while ((retcode = dbresults(dbp)) != NO_MORE_RESULTS) { if (retcode == SUCCEED && DBROWS(dbp) == SUCCEED) { list = newlistobject(0); cols = dbnumcols(dbp); fmt = (int *)malloc(sizeof(int) * cols); for (i = 1; i <= cols; i++) { switch(dbcoltype(dbp, i)) { case SYBCHAR: fmt[i-1] = SYBCHAR; break; case SYBINT1: fmt[i-1] = SYBINT1; break; case SYBINT2: fmt[i-1] = SYBINT2; break; case SYBINT4: fmt[i-1] = SYBINT4; break; case SYBFLT8: fmt[i-1] = SYBFLT8; break; } } while (dbnextrow(dbp) != NO_MORE_ROWS) { tuple = newtupleobject(cols); for (i = 1; i <= cols; i++) { switch(fmt[i-1]) { case SYBCHAR: o = newsizedstringobject((char *)dbdata(dbp, i), dbdatlen(dbp, i)); settupleitem(tuple, i-1, o); break; case SYBINT1: o = newintobject(*((char *)dbdata(dbp, i))); settupleitem(tuple, i-1, o); break; case SYBINT2: o = newintobject(*((short *)dbdata(dbp, i))); settupleitem(tuple, i-1, o); break; case SYBINT4: o = newintobject(*((int *)dbdata(dbp, i))); settupleitem(tuple, i-1, o); break; case SYBFLT8: o = newfloatobject(*((double *)dbdata(dbp, i))); settupleitem(tuple, i-1, o); break; } } addlistitem(list,tuple); } free(fmt); addlistitem(results,list); } } return (results); } static object *sybdb_sql (self, args) object *self; object *args; { char *sql; DBPROCESS *dbp; dbp = ((sybdbobject *)self)->dbproc; err_clear (); if (!getargs (args, "s", &sql)) { return NULL; } dbcancel(dbp); dbcmd(dbp, sql); dbsqlexec(dbp); return getresults(dbp); } static object *sybdb_sp (self, args) object *self; object *args; { char *sp; DBPROCESS *dbp; object *spargs; object *sparg; object *results; object *r; int spargcnt; int i; int retstatus; dbp = ((sybdbobject *)self)->dbproc; err_clear (); if (!getargs (args, "(sO)", &sp, &spargs)) { return NULL; } dbcancel(dbp); dbrpcinit(dbp, sp, 0); if (is_tupleobject(spargs)) { spargcnt=gettuplesize(spargs); for (i=0; i < spargcnt; i++) { sparg = gettupleitem(spargs,i); if (is_intobject(sparg)) { int i; i = getintvalue(sparg); dbrpcparam(dbp, NULL, 0, SYBINT4, -1, -1, &i); } else if (is_floatobject(sparg)) { double i; i = getfloatvalue(sparg); dbrpcparam(dbp, NULL, 0, SYBFLT8, -1, -1, &i); } else if (is_stringobject(sparg)) { dbrpcparam(dbp, NULL, 0, SYBCHAR, -1, getstringsize(sparg), getstringvalue(sparg)); } else { err_setstr (SybaseError, "Could not handle paramaters to procedure."); return NULL; } } } else if (spargs != None) { err_setstr (SybaseError, "Could not handle paramaters to procedure."); return NULL; } dbrpcsend(dbp); dbsqlok(dbp); results = getresults(dbp); retstatus = dbretstatus(dbp); r = mkvalue("(iO)", retstatus, results); DECREF(results); return (r); } static struct methodlist sybdb_methods[] = { {"sql", sybdb_sql}, {"sp", sybdb_sp}, {NULL, NULL} /* sentinel */ }; static void sybdb_dealloc(s) sybdbobject *s; { dbloginfree(s->login); dbclose(s->dbproc); DEL(s); } static object * sybdb_getattr(s, name) sybdbobject *s; char *name; { return findmethod(sybdb_methods, (object *) s, name); } typeobject SybDbtype = { OB_HEAD_INIT(&Typetype) 0, "sybdb", sizeof(sybdbobject), 0, sybdb_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ sybdb_getattr, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ }; /* MODULE FUNCTIONS: sybase */ static object *sybase_new (self, args) object *self; /* Not used */ object *args; { char *user, *passwd, *server; object *db; err_clear (); if (!getargs (args, "(zzz)", &user, &passwd, &server)) { return NULL; } db = (object *) newsybdbobject(user, passwd, server); if (!db) { /* XXX Should be setting some errstr stuff here based on sybase errors */ err_setstr (SybaseError, "Could not open connection to server."); return NULL; } return db; } /* List of module functions */ static struct methodlist sybase_methods[]= { {"new", sybase_new}, {NULL, NULL} /* sentinel */ }; /* Module initialisation */ void initsybase () { object *m, *d; /* Create the module and add the functions */ m = initmodule ("sybase", sybase_methods); /* Add some symbolic constants to the module */ d = getmoduledict (m); SybaseError = newstringobject ("sybase.error"); if (SybaseError == NULL || dictinsert (d, "error", SybaseError) != 0) { fatal ("can't define sybase.error"); } /* Check for errors */ if (err_occurred ()){ fatal ("can't initialize module sybase"); } }