Re: Sybase module -- input sought

jredford@lehman.com
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 <Py/allobjects.h>
#include <Py/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");
}
}