blob: 860203fbfc2608567941dde40ec21c8304415a9b [file] [log] [blame]
Guido van Rossum398d9fe1994-05-11 08:59:13 +00001/*
2Subject: Re: Sybase module -- input sought
3From: jredford@lehman.com
4To: ags@uncompaghre.informatics.jax.org (Alexander G. Smith)
5Cc: python-list@cwi.nl
6Date: Tue, 10 May 94 11:53:13 -0400
7
8
9input sought? how about a complete module? :)
10
11This is a fairly incomplete work.. but I have done things dramatically
12differently than sybperl would. Given the nature of the language I
13find it is easier to simply get ALL results & then muck with the rows
14later as parts of the data. This is a subset of the functionality of a
15Modula-3 interface to Sybase that I wrote.. I could send you that if
16you 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
28static object *SybaseError; /* exception sybase.error */
29
30
31typedef struct {
32 OB_HEAD
33 LOGINREC *login; /* login record */
34 DBPROCESS *dbproc; /* login record */
35} sybdbobject;
36
37extern typeobject SybDbtype; /* Forward */
38
39
40static 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 */
66static 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
138static object
139 *sybdb_sql (self, args)
140object *self;
141object *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
157static object
158 *sybdb_sp (self, args)
159object *self;
160object *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
216static struct methodlist sybdb_methods[] = {
217 {"sql", sybdb_sql},
218 {"sp", sybdb_sp},
219 {NULL, NULL} /* sentinel */
220};
221
222static void
223sybdb_dealloc(s)
224 sybdbobject *s;
225{
226 dbloginfree(s->login);
227 dbclose(s->dbproc);
228 DEL(s);
229}
230
231static object *
232sybdb_getattr(s, name)
233 sybdbobject *s;
234 char *name;
235{
236 return findmethod(sybdb_methods, (object *) s, name);
237}
238
239
240typeobject 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
263static object
264 *sybase_new (self, args)
265object *self; /* Not used */
266object *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 */
286static struct methodlist sybase_methods[]=
287{
288 {"new", sybase_new},
289 {NULL, NULL} /* sentinel */
290};
291
292/* Module initialisation */
293void 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}