Guido van Rossum | 398d9fe | 1994-05-11 08:59:13 +0000 | [diff] [blame] | 1 | /* |
| 2 | Subject: Re: Sybase module -- input sought |
| 3 | From: jredford@lehman.com |
| 4 | To: ags@uncompaghre.informatics.jax.org (Alexander G. Smith) |
| 5 | Cc: python-list@cwi.nl |
| 6 | Date: Tue, 10 May 94 11:53:13 -0400 |
| 7 | |
| 8 | |
| 9 | input sought? how about a complete module? :) |
| 10 | |
| 11 | This is a fairly incomplete work.. but I have done things dramatically |
| 12 | differently than sybperl would. Given the nature of the language I |
| 13 | find it is easier to simply get ALL results & then muck with the rows |
| 14 | later as parts of the data. This is a subset of the functionality of a |
| 15 | Modula-3 interface to Sybase that I wrote.. I could send you that if |
| 16 | you are interested in a more complete picture. |
| 17 | */ |
| 18 | |
| 19 | #include <stdio.h> |
| 20 | |
| 21 | #include <sybfront.h> |
| 22 | #include <sybdb.h> |
| 23 | |
| 24 | #include "allobjects.h" |
| 25 | #include "modsupport.h" |
| 26 | |
| 27 | |
| 28 | static object *SybaseError; /* exception sybase.error */ |
| 29 | |
| 30 | |
| 31 | typedef struct { |
| 32 | OB_HEAD |
| 33 | LOGINREC *login; /* login record */ |
| 34 | DBPROCESS *dbproc; /* login record */ |
| 35 | } sybdbobject; |
| 36 | |
| 37 | extern typeobject SybDbtype; /* Forward */ |
| 38 | |
| 39 | |
| 40 | static sybdbobject * |
| 41 | newsybdbobject(char *user, char *passwd, char *server) |
| 42 | { |
| 43 | sybdbobject *s; |
| 44 | |
| 45 | s = NEWOBJ(sybdbobject, &SybDbtype); |
| 46 | if (s != NULL) { |
| 47 | s->login = dblogin(); |
| 48 | if (user) { |
| 49 | (void)DBSETLUSER(s->login, user); |
| 50 | } |
| 51 | if (passwd) { |
| 52 | (void)DBSETLPWD(s->login, passwd); |
| 53 | } |
| 54 | if(!(s->dbproc = dbopen(s->login, server))) { |
| 55 | dbloginfree(s->login); |
| 56 | DEL(s); |
| 57 | return (NULL); |
| 58 | } |
| 59 | } |
| 60 | return s; |
| 61 | } |
| 62 | |
| 63 | /* OBJECT FUNCTIONS: sybdb */ |
| 64 | |
| 65 | /* Common code for returning pending results */ |
| 66 | static object |
| 67 | *getresults (DBPROCESS *dbp) |
| 68 | { |
| 69 | object *results; |
| 70 | object *list; |
| 71 | object *tuple; |
| 72 | object *o; |
| 73 | int retcode; |
| 74 | int cols; |
| 75 | int *fmt; |
| 76 | int i; |
| 77 | |
| 78 | results = newlistobject(0); |
| 79 | while ((retcode = dbresults(dbp)) != NO_MORE_RESULTS) { |
| 80 | if (retcode == SUCCEED && DBROWS(dbp) == SUCCEED) { |
| 81 | list = newlistobject(0); |
| 82 | cols = dbnumcols(dbp); |
| 83 | fmt = (int *)malloc(sizeof(int) * cols); |
| 84 | for (i = 1; i <= cols; i++) { |
| 85 | switch(dbcoltype(dbp, i)) { |
| 86 | case SYBCHAR: |
| 87 | fmt[i-1] = SYBCHAR; |
| 88 | break; |
| 89 | case SYBINT1: |
| 90 | fmt[i-1] = SYBINT1; |
| 91 | break; |
| 92 | case SYBINT2: |
| 93 | fmt[i-1] = SYBINT2; |
| 94 | break; |
| 95 | case SYBINT4: |
| 96 | fmt[i-1] = SYBINT4; |
| 97 | break; |
| 98 | case SYBFLT8: |
| 99 | fmt[i-1] = SYBFLT8; |
| 100 | break; |
| 101 | } |
| 102 | } |
| 103 | while (dbnextrow(dbp) != NO_MORE_ROWS) { |
| 104 | tuple = newtupleobject(cols); |
| 105 | for (i = 1; i <= cols; i++) { |
| 106 | switch(fmt[i-1]) { |
| 107 | case SYBCHAR: |
| 108 | o = newsizedstringobject((char *)dbdata(dbp, i), dbdatlen(dbp, i)); |
| 109 | settupleitem(tuple, i-1, o); |
| 110 | break; |
| 111 | case SYBINT1: |
| 112 | o = newintobject(*((char *)dbdata(dbp, i))); |
| 113 | settupleitem(tuple, i-1, o); |
| 114 | break; |
| 115 | case SYBINT2: |
| 116 | o = newintobject(*((short *)dbdata(dbp, i))); |
| 117 | settupleitem(tuple, i-1, o); |
| 118 | break; |
| 119 | case SYBINT4: |
| 120 | o = newintobject(*((int *)dbdata(dbp, i))); |
| 121 | settupleitem(tuple, i-1, o); |
| 122 | break; |
| 123 | case SYBFLT8: |
| 124 | o = newfloatobject(*((double *)dbdata(dbp, i))); |
| 125 | settupleitem(tuple, i-1, o); |
| 126 | break; |
| 127 | } |
| 128 | } |
| 129 | addlistitem(list,tuple); |
| 130 | } |
| 131 | free(fmt); |
| 132 | addlistitem(results,list); |
| 133 | } |
| 134 | } |
| 135 | return (results); |
| 136 | } |
| 137 | |
| 138 | static object |
| 139 | *sybdb_sql (self, args) |
| 140 | object *self; |
| 141 | object *args; |
| 142 | { |
| 143 | char *sql; |
| 144 | DBPROCESS *dbp; |
| 145 | |
| 146 | dbp = ((sybdbobject *)self)->dbproc; |
| 147 | err_clear (); |
| 148 | if (!getargs (args, "s", &sql)) { |
| 149 | return NULL; |
| 150 | } |
| 151 | dbcancel(dbp); |
| 152 | dbcmd(dbp, sql); |
| 153 | dbsqlexec(dbp); |
| 154 | return getresults(dbp); |
| 155 | } |
| 156 | |
| 157 | static object |
| 158 | *sybdb_sp (self, args) |
| 159 | object *self; |
| 160 | object *args; |
| 161 | { |
| 162 | char *sp; |
| 163 | DBPROCESS *dbp; |
| 164 | object *spargs; |
| 165 | object *sparg; |
| 166 | object *results; |
| 167 | object *r; |
| 168 | int spargcnt; |
| 169 | int i; |
| 170 | int retstatus; |
| 171 | |
| 172 | dbp = ((sybdbobject *)self)->dbproc; |
| 173 | err_clear (); |
| 174 | if (!getargs (args, "(sO)", &sp, &spargs)) { |
| 175 | return NULL; |
| 176 | } |
| 177 | |
| 178 | dbcancel(dbp); |
| 179 | dbrpcinit(dbp, sp, 0); |
| 180 | |
| 181 | if (is_tupleobject(spargs)) { |
| 182 | spargcnt=gettuplesize(spargs); |
| 183 | for (i=0; i < spargcnt; i++) { |
| 184 | sparg = gettupleitem(spargs,i); |
| 185 | if (is_intobject(sparg)) { |
| 186 | int i; |
| 187 | i = getintvalue(sparg); |
| 188 | dbrpcparam(dbp, NULL, 0, SYBINT4, -1, -1, &i); |
| 189 | } else if (is_floatobject(sparg)) { |
| 190 | double i; |
| 191 | i = getfloatvalue(sparg); |
| 192 | dbrpcparam(dbp, NULL, 0, SYBFLT8, -1, -1, &i); |
| 193 | } else if (is_stringobject(sparg)) { |
| 194 | dbrpcparam(dbp, NULL, 0, SYBCHAR, -1, getstringsize(sparg), getstringvalue(sparg)); |
| 195 | } else { |
| 196 | err_setstr (SybaseError, "Could not handle paramaters to procedure."); |
| 197 | return NULL; |
| 198 | } |
| 199 | } |
| 200 | } else if (spargs != None) { |
| 201 | err_setstr (SybaseError, "Could not handle paramaters to procedure."); |
| 202 | return NULL; |
| 203 | } |
| 204 | dbrpcsend(dbp); |
| 205 | dbsqlok(dbp); |
| 206 | |
| 207 | results = getresults(dbp); |
| 208 | retstatus = dbretstatus(dbp); |
| 209 | |
| 210 | r = mkvalue("(iO)", retstatus, results); |
| 211 | DECREF(results); |
| 212 | return (r); |
| 213 | } |
| 214 | |
| 215 | |
| 216 | static struct methodlist sybdb_methods[] = { |
| 217 | {"sql", sybdb_sql}, |
| 218 | {"sp", sybdb_sp}, |
| 219 | {NULL, NULL} /* sentinel */ |
| 220 | }; |
| 221 | |
| 222 | static void |
| 223 | sybdb_dealloc(s) |
| 224 | sybdbobject *s; |
| 225 | { |
| 226 | dbloginfree(s->login); |
| 227 | dbclose(s->dbproc); |
| 228 | DEL(s); |
| 229 | } |
| 230 | |
| 231 | static object * |
| 232 | sybdb_getattr(s, name) |
| 233 | sybdbobject *s; |
| 234 | char *name; |
| 235 | { |
| 236 | return findmethod(sybdb_methods, (object *) s, name); |
| 237 | } |
| 238 | |
| 239 | |
| 240 | typeobject SybDbtype = { |
| 241 | OB_HEAD_INIT(&Typetype) |
| 242 | 0, |
| 243 | "sybdb", |
| 244 | sizeof(sybdbobject), |
| 245 | 0, |
| 246 | sybdb_dealloc, /*tp_dealloc*/ |
| 247 | 0, /*tp_print*/ |
| 248 | sybdb_getattr, /*tp_getattr*/ |
| 249 | 0, /*tp_setattr*/ |
| 250 | 0, /*tp_compare*/ |
| 251 | 0, /*tp_repr*/ |
| 252 | 0, /*tp_as_number*/ |
| 253 | 0, /*tp_as_sequence*/ |
| 254 | 0, /*tp_as_mapping*/ |
| 255 | }; |
| 256 | |
| 257 | |
| 258 | |
| 259 | |
| 260 | |
| 261 | /* MODULE FUNCTIONS: sybase */ |
| 262 | |
| 263 | static object |
| 264 | *sybase_new (self, args) |
| 265 | object *self; /* Not used */ |
| 266 | object *args; |
| 267 | { |
| 268 | char *user, *passwd, *server; |
| 269 | object *db; |
| 270 | |
| 271 | err_clear (); |
| 272 | if (!getargs (args, "(zzz)", &user, &passwd, &server)) { |
| 273 | return NULL; |
| 274 | } |
| 275 | db = (object *) newsybdbobject(user, passwd, server); |
| 276 | if (!db) { |
| 277 | /* XXX Should be setting some errstr stuff here based on sybase errors */ |
| 278 | err_setstr (SybaseError, "Could not open connection to server."); |
| 279 | return NULL; |
| 280 | } |
| 281 | return db; |
| 282 | } |
| 283 | |
| 284 | |
| 285 | /* List of module functions */ |
| 286 | static struct methodlist sybase_methods[]= |
| 287 | { |
| 288 | {"new", sybase_new}, |
| 289 | {NULL, NULL} /* sentinel */ |
| 290 | }; |
| 291 | |
| 292 | /* Module initialisation */ |
| 293 | void initsybase () |
| 294 | { |
| 295 | object *m, *d; |
| 296 | |
| 297 | /* Create the module and add the functions */ |
| 298 | m = initmodule ("sybase", sybase_methods); |
| 299 | /* Add some symbolic constants to the module */ |
| 300 | d = getmoduledict (m); |
| 301 | SybaseError = newstringobject ("sybase.error"); |
| 302 | if (SybaseError == NULL || dictinsert (d, "error", SybaseError) != 0) { |
| 303 | fatal ("can't define sybase.error"); |
| 304 | } |
| 305 | /* Check for errors */ |
| 306 | if (err_occurred ()){ |
| 307 | fatal ("can't initialize module sybase"); |
| 308 | } |
| 309 | } |