| /* | 
 | 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 <stdio.h> | 
 |  | 
 | #include <sybfront.h> | 
 | #include <sybdb.h> | 
 |  | 
 | #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"); | 
 |   } | 
 | } |