]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/myingres.c
ea41efdc3f5975f498f159308920ae922bc1f590
[bacula/bacula] / bacula / src / cats / myingres.c
1 #include "bacula.h"
2 /* # line 3 "myingres.sc" */    
3 #ifdef HAVE_INGRES
4 #include <eqpname.h>
5 #include <eqdefcc.h>
6 #include <eqsqlca.h>
7 extern IISQLCA sqlca;   /* SQL Communications Area */
8 #include <eqsqlda.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include "myingres.h"
13 /*
14  * ---Implementations---
15  */
16 int INGcheck()
17 {
18    return (sqlca.sqlcode < 0) ? sqlca.sqlcode : 0;
19 }
20 short INGgetCols(B_DB *mdb, const char *query)
21 {
22    bool stmt_free = false;
23 /* # line 24 "myingres.sc" */   
24   
25   char *stmt;
26 /* # line 26 "myingres.sc" */   
27   
28    short number = 1;
29    IISQLDA *sqlda;
30    sqlda = (IISQLDA *)malloc(IISQDA_HEAD_SIZE + (number * IISQDA_VAR_SIZE));
31    memset(sqlda, 0, (IISQDA_HEAD_SIZE + (number * IISQDA_VAR_SIZE)));
32    sqlda->sqln = number;
33    /*
34     * See if we need to run this through the limit_filter.
35     */
36    if (strstr(query, "LIMIT") != NULL) {
37       stmt = mdb->limit_filter->replace(query);
38    } else {
39       stmt = bstrdup(query);
40       stmt_free = true;
41    }
42 /* # line 46 "myingres.sc" */   /* prepare */
43   {
44     IIsqInit(&sqlca);
45     IIsqPrepare(0,(char *)"s1",(char *)0,0,stmt);
46   }
47 /* # line 47 "myingres.sc" */   /* host code */
48    if (INGcheck() < 0) {
49       number = -1;
50       goto bail_out;
51    }
52 /* # line 52 "myingres.sc" */   /* describe */
53   {
54     IIsqInit(&sqlca);
55     IIsqDescribe(0,(char *)"s1",sqlda,0);
56   }
57 /* # line 53 "myingres.sc" */   /* host code */
58    if (INGcheck() < 0) {
59       number = -1;
60       goto bail_out;
61    }
62    number = sqlda->sqld;
63 bail_out:
64    if (stmt_free) {
65       free(stmt);
66    }
67    free(sqlda);
68    return number;
69 }
70 static inline IISQLDA *INGgetDescriptor(B_DB *mdb, short numCols, const char *query)
71 {
72    bool stmt_free = false;
73 /* # line 71 "myingres.sc" */   
74   
75   char *stmt;
76 /* # line 73 "myingres.sc" */   
77   
78    int i;
79    IISQLDA *sqlda;
80    sqlda = (IISQLDA *)malloc(IISQDA_HEAD_SIZE + (numCols * IISQDA_VAR_SIZE));
81    memset(sqlda, 0, (IISQDA_HEAD_SIZE + (numCols * IISQDA_VAR_SIZE)));
82    sqlda->sqln = numCols;
83    /*
84     * See if we need to run this through the limit_filter.
85     */
86    if (strstr(query, "LIMIT") != NULL) {
87       stmt = mdb->limit_filter->replace(query);
88    } else {
89       stmt = bstrdup(query);
90       stmt_free = true;
91    }
92 /* # line 93 "myingres.sc" */   /* prepare */
93   {
94     IIsqInit(&sqlca);
95     IIsqPrepare(0,(char *)"s2",sqlda,0,stmt);
96   }
97 /* # line 95 "myingres.sc" */   /* host code */
98    if (stmt_free) {
99       free(stmt);
100    }
101    for (i = 0; i < sqlda->sqld; ++i) {
102       /*
103        * Negative type indicates nullable coulumns, so an indicator
104        * is allocated, otherwise it's null
105        */
106       if (sqlda->sqlvar[i].sqltype > 0) {
107          sqlda->sqlvar[i].sqlind = NULL;
108       } else {
109          sqlda->sqlvar[i].sqlind = (short *)malloc(sizeof(short));
110       }
111       /*
112        * Alloc space for variable like indicated in sqllen
113        * for date types sqllen is always 0 -> allocate by type
114        */
115       switch (abs(sqlda->sqlvar[i].sqltype)) {
116       case IISQ_TSW_TYPE:
117          sqlda->sqlvar[i].sqldata = (char *)malloc(IISQ_TSW_LEN);
118          break;
119       case IISQ_TSWO_TYPE:
120          sqlda->sqlvar[i].sqldata = (char *)malloc(IISQ_TSWO_LEN);
121          break;
122       case IISQ_TSTMP_TYPE:
123          sqlda->sqlvar[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN);
124          break;
125       default:
126          /*
127           * plus one to avoid zero mem allocs
128           */
129          sqlda->sqlvar[i].sqldata = (char *)malloc(sqlda->sqlvar[i].sqllen+1);
130          break;
131       }
132    }
133    return sqlda;
134 }
135 static void INGfreeDescriptor(IISQLDA *sqlda)
136 {
137    int i;
138    if (!sqlda) {
139       return;
140    }
141    for (i = 0; i < sqlda->sqld; ++i) {
142       if (sqlda->sqlvar[i].sqldata) {
143          free(sqlda->sqlvar[i].sqldata);
144       }
145       if (sqlda->sqlvar[i].sqlind) {
146          free(sqlda->sqlvar[i].sqlind);
147       }
148    }
149    free(sqlda);
150    sqlda = NULL;
151 }
152 static inline int INGgetTypeSize(IISQLVAR *ingvar)
153 {
154    int inglength = 0;
155    /*
156     * TODO: add date types (at least TSTMP,TSW TSWO)
157     */
158    switch (ingvar->sqltype) {
159    case IISQ_DTE_TYPE:
160       inglength = 25;
161       break;
162    case IISQ_MNY_TYPE:
163       inglength = 8;
164       break;
165    default:
166       inglength = ingvar->sqllen;
167       break;
168    }
169    return inglength;
170 }
171 static inline INGresult *INGgetINGresult(IISQLDA *sqlda)
172 {
173    int i;
174    INGresult *result = NULL;
175    if (!sqlda) {
176       return NULL;
177    }
178    result = (INGresult *)malloc(sizeof(INGresult));
179    memset(result, 0, sizeof(INGresult));
180    result->sqlda = sqlda;
181    result->num_fields = sqlda->sqld;
182    result->num_rows = 0;
183    result->first_row = NULL;
184    result->status = ING_EMPTY_RESULT;
185    result->act_row = NULL;
186    memset(result->numrowstring, 0, sizeof(result->numrowstring));
187    if (result->num_fields) {
188       result->fields = (INGRES_FIELD *)malloc(sizeof(INGRES_FIELD) * result->num_fields);
189       memset(result->fields, 0, sizeof(INGRES_FIELD) * result->num_fields);
190       for (i = 0; i < result->num_fields; ++i) {
191          memset(result->fields[i].name, 0, 34);
192          bstrncpy(result->fields[i].name, sqlda->sqlvar[i].sqlname.sqlnamec, sqlda->sqlvar[i].sqlname.sqlnamel);
193          result->fields[i].max_length = INGgetTypeSize(&sqlda->sqlvar[i]);
194          result->fields[i].type = abs(sqlda->sqlvar[i].sqltype);
195          result->fields[i].flags = (sqlda->sqlvar[i].sqltype < 0) ? 1 : 0;
196       }
197    }
198    return result;
199 }
200 static void INGfreeINGresult(INGresult *ing_res)
201 {
202    int rows;
203    ING_ROW *rowtemp;
204    if (!ing_res) {
205       return;
206    }
207    /*
208     * Free all rows and fields, then res, not descriptor!
209     *
210     * Use of rows is a nasty workaround til I find the reason,
211     * why aggregates like max() don't work
212     */
213    rows = ing_res->num_rows;
214    ing_res->act_row = ing_res->first_row;
215    while (ing_res->act_row != NULL && rows > 0) {
216       rowtemp = ing_res->act_row->next;
217       INGfreeRowSpace(ing_res->act_row, ing_res->sqlda);
218       ing_res->act_row = rowtemp;
219       --rows;
220    }
221    if (ing_res->fields) {
222       free(ing_res->fields);
223    }
224    free(ing_res);
225    ing_res = NULL;
226 }
227 static inline ING_ROW *INGgetRowSpace(INGresult *ing_res)
228 {
229    int i;
230    unsigned short len; /* used for VARCHAR type length */
231    IISQLDA *sqlda = ing_res->sqlda;
232    ING_ROW *row = NULL;
233    IISQLVAR *vars = NULL;
234    row = (ING_ROW *)malloc(sizeof(ING_ROW));
235    memset(row, 0, sizeof(ING_ROW));
236    vars = (IISQLVAR *)malloc(sizeof(IISQLVAR) * sqlda->sqld);
237    memset(vars, 0, sizeof(IISQLVAR) * sqlda->sqld);
238    row->sqlvar = vars;
239    row->next = NULL;
240    for (i = 0; i < sqlda->sqld; ++i) {
241       /*
242        * Make strings out of the data, then the space and assign 
243        * (why string? at least it seems that way, looking into the sources)
244        */
245       vars[i].sqlind = (short *)malloc(sizeof(short));
246       if (sqlda->sqlvar[i].sqlind) {
247          memcpy(vars[i].sqlind,sqlda->sqlvar[i].sqlind,sizeof(short));
248       } else {
249          *vars[i].sqlind = NULL;
250       }
251       /*
252        * if sqlind pointer exists AND points to -1 -> column is 'null'
253        */
254       if ( *vars[i].sqlind && (*vars[i].sqlind == -1)) {
255          vars[i].sqldata = NULL;
256       } else {
257          switch (ing_res->fields[i].type) {
258          case IISQ_VCH_TYPE:
259             len = ((ING_VARCHAR *)sqlda->sqlvar[i].sqldata)->len;
260             vars[i].sqldata = (char *)malloc(len+1);
261             memcpy(vars[i].sqldata,sqlda->sqlvar[i].sqldata+2,len);
262             vars[i].sqldata[len] = '\0';
263             break;
264          case IISQ_CHA_TYPE:
265             vars[i].sqldata = (char *)malloc(ing_res->fields[i].max_length+1);
266             memcpy(vars[i].sqldata,sqlda->sqlvar[i].sqldata,sqlda->sqlvar[i].sqllen);
267             vars[i].sqldata[ing_res->fields[i].max_length] = '\0';
268             break;
269          case IISQ_INT_TYPE:
270             vars[i].sqldata = (char *)malloc(20);
271             memset(vars[i].sqldata, 0, 20);
272             switch (sqlda->sqlvar[i].sqllen) {
273             case 2:
274                bsnprintf(vars[i].sqldata, 20, "%d",*(short*)sqlda->sqlvar[i].sqldata);
275                break;
276             case 4:
277                bsnprintf(vars[i].sqldata, 20, "%ld",*(int*)sqlda->sqlvar[i].sqldata);
278                break;
279             case 8:
280                bsnprintf(vars[i].sqldata, 20, "%lld",*(long*)sqlda->sqlvar[i].sqldata);
281                break;
282             }
283             break;
284          case IISQ_TSTMP_TYPE:
285             vars[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN+1);
286             vars[i].sqldata[IISQ_TSTMP_LEN] = '\0';
287             break;
288          case IISQ_TSWO_TYPE:
289             vars[i].sqldata = (char *)malloc(IISQ_TSWO_LEN+1);
290             vars[i].sqldata[IISQ_TSWO_LEN] = '\0';
291             break;
292          case IISQ_TSW_TYPE:
293             vars[i].sqldata = (char *)malloc(IISQ_TSW_LEN+1);
294             vars[i].sqldata[IISQ_TSW_LEN] = '\0';
295             break;
296          }
297       }
298    }
299    return row;
300 }
301 static inline void INGfreeRowSpace(ING_ROW *row, IISQLDA *sqlda)
302 {
303    int i;
304    if (row == NULL || sqlda == NULL) {
305       return;
306    }
307    for (i = 0; i < sqlda->sqld; ++i) {
308       if (row->sqlvar[i].sqldata) {
309          free(row->sqlvar[i].sqldata);
310       }
311       if (row->sqlvar[i].sqlind) {
312          free(row->sqlvar[i].sqlind);
313       }
314    }
315    free(row->sqlvar);
316    free(row);
317 }
318 static inline int INGfetchAll(const char *query, INGresult *ing_res)
319 {
320    int linecount = 0;
321    ING_ROW *row;
322    IISQLDA *desc;
323    int check = -1;
324    desc = ing_res->sqlda;
325 /* # line 352 "myingres.sc" */  /* host code */
326    if ((check = INGcheck()) < 0) {
327       return check;
328    }
329 /* # line 356 "myingres.sc" */  /* open */
330   {
331     IIsqInit(&sqlca);
332     IIcsOpen((char *)"c2",9209,14491);
333     IIwritio(0,(short *)0,1,32,0,(char *)"s2");
334     IIcsQuery((char *)"c2",9209,14491);
335   }
336 /* # line 357 "myingres.sc" */  /* host code */
337    if ((check = INGcheck()) < 0) {
338       return check;
339    }
340    /* for (linecount = 0; sqlca.sqlcode == 0; ++linecount) */
341    do {
342 /* # line 363 "myingres.sc" */  /* fetch */
343   {
344     IIsqInit(&sqlca);
345     if (IIcsRetScroll((char *)"c2",9209,14491,-1,-1) != 0) {
346       IIcsDaGet(0,desc);
347       IIcsERetrieve();
348     } /* IIcsRetrieve */
349   }
350 /* # line 365 "myingres.sc" */  /* host code */
351       if ( (sqlca.sqlcode == 0) || (sqlca.sqlcode == -40202) ) {
352          row = INGgetRowSpace(ing_res); /* alloc space for fetched row */
353          /*
354           * Initialize list when encountered first time
355           */
356          if (ing_res->first_row == 0) {
357             ing_res->first_row = row; /* head of the list */
358             ing_res->first_row->next = NULL;
359             ing_res->act_row = ing_res->first_row;
360          }      
361          ing_res->act_row->next = row; /* append row to old act_row */
362          ing_res->act_row = row; /* set row as act_row */
363          row->row_number = linecount;
364          ++linecount;
365       }
366    } while ( (sqlca.sqlcode == 0) || (sqlca.sqlcode == -40202) );
367 /* # line 383 "myingres.sc" */  /* close */
368   {
369     IIsqInit(&sqlca);
370     IIcsClose((char *)"c2",9209,14491);
371   }
372 /* # line 385 "myingres.sc" */  /* host code */
373    ing_res->status = ING_COMMAND_OK;
374    ing_res->num_rows = linecount;
375    return linecount;
376 }
377 static inline ING_STATUS INGresultStatus(INGresult *res)
378 {
379    if (res == NULL) {
380       return ING_NO_RESULT;
381    } else {
382       return res->status;
383    }
384 }
385 static void INGrowSeek(INGresult *res, int row_number)
386 {
387    ING_ROW *trow = NULL;
388    if (res->act_row->row_number == row_number) {
389       return;
390    }
391    /*
392     * TODO: real error handling
393     */
394    if (row_number<0 || row_number>res->num_rows) {
395       return;
396    }
397    for (trow = res->first_row; trow->row_number != row_number; trow = trow->next) ;
398    res->act_row = trow;
399    /*
400     * Note - can be null - if row_number not found, right?
401     */
402 }
403 char *INGgetvalue(INGresult *res, int row_number, int column_number)
404 {
405    if (row_number != res->act_row->row_number) {
406       INGrowSeek(res, row_number);
407    }
408    return res->act_row->sqlvar[column_number].sqldata;
409 }
410 int INGgetisnull(INGresult *res, int row_number, int column_number)
411 {
412    if (row_number != res->act_row->row_number) {
413       INGrowSeek(res, row_number);
414    }
415    return (*res->act_row->sqlvar[column_number].sqlind == -1) 1 : 0;
416 }
417 int INGntuples(const INGresult *res)
418 {
419    return res->num_rows;
420 }
421 int INGnfields(const INGresult *res)
422 {
423    return res->num_fields;
424 }
425 char *INGfname(const INGresult *res, int column_number)
426 {
427    if ((column_number > res->num_fields) || (column_number < 0)) {
428       return NULL;
429    } else {
430       return res->fields[column_number].name;
431    }
432 }
433 short INGftype(const INGresult *res, int column_number)
434 {
435    return res->fields[column_number].type;
436 }
437 int INGexec(B_DB *mdb, INGconn *conn, const char *query)
438 {
439    bool stmt_free = false;
440    int check;
441 /* # line 467 "myingres.sc" */  
442   
443   int rowcount;
444   char *stmt;
445 /* # line 470 "myingres.sc" */  
446   
447    /*
448     * See if we need to run this through the limit_filter.
449     */
450    if (strstr(query, "LIMIT") != NULL) {
451       stmt = mdb->limit_filter->replace(query);
452    } else {
453       stmt = bstrdup(query);
454       stmt_free = true;
455    }
456    rowcount = -1;
457 /* # line 483 "myingres.sc" */  /* execute */
458   {
459     IIsqInit(&sqlca);
460     IIsqExImmed(stmt);
461     IIsyncup((char *)0,0);
462   }
463 /* # line 485 "myingres.sc" */  /* host code */
464    if (stmt_free) {
465       free(stmt);
466    }
467    if ((check = INGcheck()) < 0) {
468       return check;
469    }
470 /* # line 493 "myingres.sc" */  /* inquire_ingres */
471   {
472     IILQisInqSqlio((short *)0,1,30,sizeof(rowcount),&rowcount,8);
473   }
474 /* # line 494 "myingres.sc" */  /* host code */
475    if ((check = INGcheck()) < 0) {
476       return check;
477    }
478    return rowcount;
479 }
480 INGresult *INGquery(B_DB *mdb, INGconn *conn, const char *query)
481 {
482    /*
483     * TODO: error handling
484     */
485    IISQLDA *desc = NULL;
486    INGresult *res = NULL;
487    int rows = -1;
488    int cols = INGgetCols(mdb, query);
489    desc = INGgetDescriptor(cols, query);
490    if (!desc) {
491       return NULL;
492    }
493    res = INGgetINGresult(desc);
494    if (!res) {
495       return NULL;
496    }
497    rows = INGfetchAll(query, res);
498    if (rows < 0) {
499      INGfreeINGresult(res);
500      INGfreeDescriptor(desc);
501      return NULL;
502    }
503    return res;
504 }
505 void INGclear(INGresult *res)
506 {
507    if (res == NULL) {
508       return;
509    }
510    INGfreeINGresult(res);
511    INGfreeDescriptor(res->sqlda);
512 }
513 INGconn *INGconnectDB(char *dbname, char *user, char *passwd)
514 {
515    INGconn *dbconn;
516    if (dbname == NULL || strlen(dbname) == 0) {
517       return NULL;
518    }
519    dbconn = (INGconn *)malloc(sizeof(INGconn));
520    memset(dbconn, 0, sizeof(INGconn));
521 /* # line 550 "myingres.sc" */  
522   
523   char ingdbname[24];
524   char ingdbuser[32];
525   char ingdbpasw[32];
526   char conn_name[32];
527   int sess_id;
528 /* # line 556 "myingres.sc" */  
529   
530    bstrncpy(ingdbname, dbname, sizeof(ingdbname));
531    if (user != NULL) {
532       bstrncpy(ingdbuser, user, sizeof(ingdbuser));
533       if (passwd != NULL) {
534          bstrncpy(ingdbpasw, passwd, sizeof(ingdbpasw));
535       } else {
536          memset(ingdbpasw, 0, sizeof(ingdbpasw));
537       }
538 /* # line 567 "myingres.sc" */  /* connect */
539   {
540     IIsqInit(&sqlca);
541     IIsqUser(ingdbuser);
542     IIsqConnect(0,ingdbname,(char *)"-dbms_password",ingdbpasw,(char *)0, 
543     (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, 
544     (char *)0, (char *)0, (char *)0, (char *)0);
545   }
546 /* # line 571 "myingres.sc" */  /* host code */
547    } else {
548 /* # line 572 "myingres.sc" */  /* connect */
549   {
550     IIsqInit(&sqlca);
551     IIsqConnect(0,ingdbname,(char *)0, (char *)0, (char *)0, (char *)0, 
552     (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, 
553     (char *)0, (char *)0, (char *)0);
554   }
555 /* # line 573 "myingres.sc" */  /* host code */
556    }   
557 /* # line 575 "myingres.sc" */  /* inquire_sql */
558   {
559     IILQisInqSqlio((short *)0,1,32,31,conn_name,13);
560   }
561 /* # line 576 "myingres.sc" */  /* inquire_sql */
562   {
563     IILQisInqSqlio((short *)0,1,30,sizeof(sess_id),&sess_id,11);
564   }
565 /* # line 578 "myingres.sc" */  /* host code */
566    bstrncpy(dbconn->dbname, ingdbname, sizeof(dbconn->dbname));
567    bstrncpy(dbconn->user, ingdbuser, sizeof(dbconn->user));
568    bstrncpy(dbconn->password, ingdbpasw, sizeof(dbconn->password));
569    bstrncpy(dbconn->connection_name, conn_name, sizeof(dbconn->connection_name));
570    dbconn->session_id = sess_id;
571    dbconn->msg = (char*)malloc(257);
572    memset(dbconn->msg, 0, 257);
573    return dbconn;
574 }
575 void INGdisconnectDB(INGconn *dbconn)
576 {
577    /*
578     * TODO: check for any real use of dbconn: maybe whenn multithreaded?
579     */
580 /* # line 594 "myingres.sc" */  /* disconnect */
581   {
582     IIsqInit(&sqlca);
583     IIsqDisconnect();
584   }
585 /* # line 595 "myingres.sc" */  /* host code */
586    if (dbconn != NULL) {
587       free(dbconn->msg);
588       free(dbconn);
589    }
590 }
591 char *INGerrorMessage(const INGconn *conn)
592 {
593 /* # line 603 "myingres.sc" */  
594   
595   char errbuf[256];
596 /* # line 605 "myingres.sc" */  
597   
598 /* # line 607 "myingres.sc" */  /* inquire_ingres */
599   {
600     IILQisInqSqlio((short *)0,1,32,255,errbuf,63);
601   }
602 /* # line 608 "myingres.sc" */  /* host code */
603    memcpy(conn->msg, &errbuf, 256);
604    return conn->msg;
605 }
606 char *INGcmdTuples(INGresult *res)
607 {
608    return res->numrowstring;
609 }
610 /* TODO?
611 int INGputCopyEnd(INGconn *conn, const char *errormsg);
612 int INGputCopyData(INGconn *conn, const char *buffer, int nbytes);
613 */
614 /* # line 622 "myingres.sc" */  
615 #endif