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